merge Unix Domain Sockets support and other changes from develop

This commit is contained in:
Guenter Obiltschnig 2017-10-31 16:53:06 +01:00
parent d172273a75
commit a460bafa70
97 changed files with 2094 additions and 475 deletions

View File

@ -32,9 +32,16 @@ class Net_API DatagramSocket: public Socket
{
public:
DatagramSocket();
/// Creates an unconnected IPv4 datagram socket.
/// Creates an unconnected, unbound datagram socket.
///
/// Before the datagram socket can be used, bind(),
/// bind6() or connect() must be called.
///
/// Notice: The behavior of this constructor has changed
/// in release 2.0. Previously, the constructor created
/// an unbound IPv4 datagram socket.
explicit DatagramSocket(IPAddress::Family family);
explicit DatagramSocket(SocketAddress::Family family);
/// Creates an unconnected datagram socket.
///
/// The socket will be created for the
@ -80,6 +87,20 @@ public:
///
/// Calls to connect cannot() come before calls to bind().
void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
/// Bind a local address to the socket.
///
/// This is usually only done when establishing a server
/// socket.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
///
/// Calls to connect cannot() come before calls to bind().
int sendBytes(const void* buffer, int length, int flags = 0);
/// Sends the contents of the given buffer through
/// the socket.

View File

@ -33,7 +33,7 @@ public:
DatagramSocketImpl();
/// Creates an unconnected, unbound datagram socket.
explicit DatagramSocketImpl(IPAddress::Family family);
explicit DatagramSocketImpl(SocketAddress::Family family);
/// Creates an unconnected datagram socket.
///
/// The socket will be created for the

View File

@ -225,6 +225,24 @@ public:
/// to ensure a new connection will be set up
/// for the next request.
virtual bool peekResponse(HTTPResponse& response);
/// If the request contains a "Expect: 100-continue" header,
/// (see HTTPRequest::setExpectContinue()) this method can be
/// used to check whether the server has sent a 100 Continue response
/// before continuing with the request, i.e. sending the request body,
/// after calling sendRequest().
///
/// Returns true if the server has responded with 100 Continue,
/// otherwise false. The HTTPResponse object contains the
/// response sent by the server.
///
/// In any case, receiveResponse() must be called afterwards as well in
/// order to complete the request. The same HTTPResponse object
/// passed to peekResponse() must also be passed to receiveResponse().
///
/// This method should only be called if the request contains
/// a "Expect: 100-continue" header.
void reset();
/// Resets the session and closes the socket.
///
@ -289,6 +307,7 @@ private:
bool _reconnect;
bool _mustReconnect;
bool _expectResponseBody;
bool _responseReceived;
Poco::SharedPtr<std::ostream> _pRequestStream;
Poco::SharedPtr<std::istream> _pResponseStream;

View File

@ -103,6 +103,14 @@ public:
/// Sets the authentication scheme and information for
/// this request.
bool getExpectContinue() const;
/// Returns true if the request contains an
/// "Expect: 100-continue" header.
void setExpectContinue(bool expectContinue);
/// Adds a "Expect: 100-continue" header to the request if
/// expectContinue is true, otherwise removes the Expect header.
bool hasProxyCredentials() const;
/// Returns true iff the request contains proxy authentication
/// information in the form of an Proxy-Authorization header.
@ -141,6 +149,7 @@ public:
static const std::string AUTHORIZATION;
static const std::string PROXY_AUTHORIZATION;
static const std::string UPGRADE;
static const std::string EXPECT;
protected:
void getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const;

View File

@ -54,6 +54,11 @@ public:
/// The method should inspect the given HTTPServerRequest object (e.g., method
/// and URI) and create an appropriate HTTPRequestHandler object to handle the
/// request.
///
/// If the request contains a "Expect: 100-continue" header, it's possible
/// to prevent the server from sending the default 100 Continue response
/// by setting the status of the response object that can be obtained through
/// the request object (request.response()) to something other than 200 OK.
protected:
Poco::BasicEvent<const bool> serverStopped;

View File

@ -45,6 +45,7 @@ public:
{
HTTP_CONTINUE = 100,
HTTP_SWITCHING_PROTOCOLS = 101,
HTTP_PROCESSING = 102,
HTTP_OK = 200,
HTTP_CREATED = 201,
HTTP_ACCEPTED = 202,
@ -52,14 +53,19 @@ public:
HTTP_NO_CONTENT = 204,
HTTP_RESET_CONTENT = 205,
HTTP_PARTIAL_CONTENT = 206,
HTTP_MULTI_STATUS = 207,
HTTP_ALREADY_REPORTED = 208,
HTTP_IM_USED = 226,
HTTP_MULTIPLE_CHOICES = 300,
HTTP_MOVED_PERMANENTLY = 301,
HTTP_FOUND = 302,
HTTP_SEE_OTHER = 303,
HTTP_NOT_MODIFIED = 304,
HTTP_USEPROXY = 305,
HTTP_USE_PROXY = 305,
HTTP_USEPROXY = 305, /// @deprecated
// UNUSED: 306
HTTP_TEMPORARY_REDIRECT = 307,
HTTP_PERMANENT_REDIRECT = 308,
HTTP_BAD_REQUEST = 400,
HTTP_UNAUTHORIZED = 401,
HTTP_PAYMENT_REQUIRED = 402,
@ -73,17 +79,36 @@ public:
HTTP_GONE = 410,
HTTP_LENGTH_REQUIRED = 411,
HTTP_PRECONDITION_FAILED = 412,
HTTP_REQUESTENTITYTOOLARGE = 413,
HTTP_REQUESTURITOOLONG = 414,
HTTP_UNSUPPORTEDMEDIATYPE = 415,
HTTP_REQUEST_ENTITY_TOO_LARGE = 413,
HTTP_REQUESTENTITYTOOLARGE = 413, /// @deprecated
HTTP_REQUEST_URI_TOO_LONG = 414,
HTTP_REQUESTURITOOLONG = 414, /// @deprecated
HTTP_UNSUPPORTED_MEDIA_TYPE = 415,
HTTP_UNSUPPORTEDMEDIATYPE = 415, /// @deprecated
HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
HTTP_EXPECTATION_FAILED = 417,
HTTP_IM_A_TEAPOT = 418,
HTTP_ENCHANCE_YOUR_CALM = 420,
HTTP_MISDIRECTED_REQUEST = 421,
HTTP_UNPROCESSABLE_ENTITY = 422,
HTTP_LOCKED = 423,
HTTP_FAILED_DEPENDENCY = 424,
HTTP_UPGRADE_REQUIRED = 426,
HTTP_PRECONDITION_REQUIRED = 428,
HTTP_TOO_MANY_REQUESTS = 429,
HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
HTTP_INTERNAL_SERVER_ERROR = 500,
HTTP_NOT_IMPLEMENTED = 501,
HTTP_BAD_GATEWAY = 502,
HTTP_SERVICE_UNAVAILABLE = 503,
HTTP_GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505
HTTP_VERSION_NOT_SUPPORTED = 505,
HTTP_VARIANT_ALSO_NEGOTIATES = 506,
HTTP_INSUFFICIENT_STORAGE = 507,
HTTP_LOOP_DETECTED = 508,
HTTP_NOT_EXTENDED = 510,
HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511
};
HTTPResponse();
@ -169,6 +194,7 @@ public:
static const std::string HTTP_REASON_CONTINUE;
static const std::string HTTP_REASON_SWITCHING_PROTOCOLS;
static const std::string HTTP_REASON_PROCESSING;
static const std::string HTTP_REASON_OK;
static const std::string HTTP_REASON_CREATED;
static const std::string HTTP_REASON_ACCEPTED;
@ -176,13 +202,17 @@ public:
static const std::string HTTP_REASON_NO_CONTENT;
static const std::string HTTP_REASON_RESET_CONTENT;
static const std::string HTTP_REASON_PARTIAL_CONTENT;
static const std::string HTTP_REASON_MULTI_STATUS;
static const std::string HTTP_REASON_ALREADY_REPORTED;
static const std::string HTTP_REASON_IM_USED;
static const std::string HTTP_REASON_MULTIPLE_CHOICES;
static const std::string HTTP_REASON_MOVED_PERMANENTLY;
static const std::string HTTP_REASON_FOUND;
static const std::string HTTP_REASON_SEE_OTHER;
static const std::string HTTP_REASON_NOT_MODIFIED;
static const std::string HTTP_REASON_USEPROXY;
static const std::string HTTP_REASON_USE_PROXY;
static const std::string HTTP_REASON_TEMPORARY_REDIRECT;
static const std::string HTTP_REASON_PERMANENT_REDIRECT;
static const std::string HTTP_REASON_BAD_REQUEST;
static const std::string HTTP_REASON_UNAUTHORIZED;
static const std::string HTTP_REASON_PAYMENT_REQUIRED;
@ -196,17 +226,33 @@ public:
static const std::string HTTP_REASON_GONE;
static const std::string HTTP_REASON_LENGTH_REQUIRED;
static const std::string HTTP_REASON_PRECONDITION_FAILED;
static const std::string HTTP_REASON_REQUESTENTITYTOOLARGE;
static const std::string HTTP_REASON_REQUESTURITOOLONG;
static const std::string HTTP_REASON_UNSUPPORTEDMEDIATYPE;
static const std::string HTTP_REASON_REQUEST_ENTITY_TOO_LARGE;
static const std::string HTTP_REASON_REQUEST_URI_TOO_LONG;
static const std::string HTTP_REASON_UNSUPPORTED_MEDIA_TYPE;
static const std::string HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE;
static const std::string HTTP_REASON_EXPECTATION_FAILED;
static const std::string HTTP_REASON_IM_A_TEAPOT;
static const std::string HTTP_REASON_ENCHANCE_YOUR_CALM;
static const std::string HTTP_REASON_MISDIRECTED_REQUEST;
static const std::string HTTP_REASON_UNPROCESSABLE_ENTITY;
static const std::string HTTP_REASON_LOCKED;
static const std::string HTTP_REASON_FAILED_DEPENDENCY;
static const std::string HTTP_REASON_UPGRADE_REQUIRED;
static const std::string HTTP_REASON_PRECONDITION_REQUIRED;
static const std::string HTTP_REASON_TOO_MANY_REQUESTS;
static const std::string HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE;
static const std::string HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS;
static const std::string HTTP_REASON_INTERNAL_SERVER_ERROR;
static const std::string HTTP_REASON_NOT_IMPLEMENTED;
static const std::string HTTP_REASON_BAD_GATEWAY;
static const std::string HTTP_REASON_SERVICE_UNAVAILABLE;
static const std::string HTTP_REASON_GATEWAY_TIMEOUT;
static const std::string HTTP_REASON_VERSION_NOT_SUPPORTED;
static const std::string HTTP_REASON_VARIANT_ALSO_NEGOTIATES;
static const std::string HTTP_REASON_INSUFFICIENT_STORAGE;
static const std::string HTTP_REASON_LOOP_DETECTED;
static const std::string HTTP_REASON_NOT_EXTENDED;
static const std::string HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED;
static const std::string HTTP_REASON_UNKNOWN;
static const std::string DATE;

View File

@ -54,10 +54,6 @@ public:
/// The stream must be valid until the HTTPServerRequest
/// object is destroyed.
virtual bool expectContinue() const = 0;
/// Returns true if the client expects a
/// 100 Continue response.
virtual const SocketAddress& clientAddress() const = 0;
/// Returns the client's address.
@ -69,6 +65,12 @@ public:
virtual HTTPServerResponse& response() const = 0;
/// Returns a reference to the associated response.
virtual bool secure() const = 0;
/// Returns true if the request is using a secure
/// connection. Returns false if no secure connection
/// is used, or if it is not known whether a secure
/// connection is used.
};

View File

@ -57,10 +57,6 @@ public:
/// The stream is valid until the HTTPServerRequestImpl
/// object is destroyed.
bool expectContinue() const;
/// Returns true if the client expects a
/// 100 Continue response.
const SocketAddress& clientAddress() const;
/// Returns the client's address.
@ -73,6 +69,12 @@ public:
HTTPServerResponse& response() const;
/// Returns a reference to the associated response.
bool secure() const;
/// Returns true if the request is using a secure
/// connection. Returns false if no secure connection
/// is used, or if it is not known whether a secure
/// connection is used.
StreamSocket& socket();
/// Returns a reference to the underlying socket.
@ -83,9 +85,6 @@ public:
HTTPServerSession& session();
/// Returns the underlying HTTPServerSession.
protected:
static const std::string EXPECT;
private:
HTTPServerResponseImpl& _response;
HTTPServerSession& _session;

View File

@ -55,6 +55,9 @@ public:
void setTimeout(const Poco::Timespan& timeout);
/// Sets the timeout for the HTTP session.
void setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout);
/// Sets different timeouts for the HTTP session.
Poco::Timespan getTimeout() const;
/// Returns the timeout for the HTTP session.
@ -178,7 +181,8 @@ protected:
private:
enum
{
HTTP_DEFAULT_TIMEOUT = 60000000
HTTP_DEFAULT_TIMEOUT = 60000000,
HTTP_DEFAULT_CONNECTION_TIMEOUT = 30000000
};
HTTPSession(const HTTPSession&);
@ -189,7 +193,9 @@ private:
char* _pCurrent;
char* _pEnd;
bool _keepAlive;
Poco::Timespan _timeout;
Poco::Timespan _connectionTimeout;
Poco::Timespan _receiveTimeout;
Poco::Timespan _sendTimeout;
Poco::Exception* _pException;
Poco::Any _data;
@ -211,7 +217,7 @@ inline bool HTTPSession::getKeepAlive() const
inline Poco::Timespan HTTPSession::getTimeout() const
{
return _timeout;
return _receiveTimeout;
}

View File

@ -44,7 +44,7 @@ public:
mutable Poco::BasicEvent<ICMPEventArgs> pingError;
mutable Poco::BasicEvent<ICMPEventArgs> pingEnd;
explicit ICMPClient(IPAddress::Family family);
explicit ICMPClient(SocketAddress::Family family);
/// Creates an ICMP client.
~ICMPClient();
@ -62,7 +62,7 @@ public:
///
/// Returns the number of valid replies.
static int ping(SocketAddress& address, IPAddress::Family family, int repeat = 1);
static int ping(SocketAddress& address, SocketAddress::Family family, int repeat = 1);
/// Pings the specified address [repeat] times.
/// Notifications are not posted for events.
///
@ -75,7 +75,7 @@ public:
/// Returns the number of valid replies.
private:
mutable IPAddress::Family _family;
mutable SocketAddress::Family _family;
};

View File

@ -31,7 +31,7 @@ class Net_API ICMPPacket
/// This class is the ICMP packet abstraction.
{
public:
ICMPPacket(IPAddress::Family family, int dataSize = 48);
ICMPPacket(SocketAddress::Family family, int dataSize = 48);
/// Creates an ICMPPacket of specified family.
~ICMPPacket();

View File

@ -31,7 +31,7 @@ class Net_API ICMPSocket: public Socket
/// ICMP client socket.
{
public:
ICMPSocket(IPAddress::Family family, int dataSize = 48, int ttl = 128, int timeout = 5000000);
ICMPSocket(SocketAddress::Family family, int dataSize = 48, int ttl = 128, int timeout = 5000000);
/// Creates an unconnected ICMP socket.
///
/// The socket will be created for the

View File

@ -32,7 +32,7 @@ class Net_API ICMPSocketImpl: public RawSocketImpl
/// This class implements an ICMP socket.
{
public:
ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout);
ICMPSocketImpl(SocketAddress::Family family, int dataSize, int ttl, int timeout);
/// Creates an unconnected ICMP socket.
///
/// The socket will be created for the given address family.

View File

@ -24,6 +24,7 @@
#include "Poco/AutoPtr.h"
#include "Poco/Exception.h"
#include <vector>
#include <ostream>
namespace Poco {
@ -55,14 +56,14 @@ class Net_API IPAddress
public:
typedef std::vector<IPAddress> List;
enum Family
/// Possible address families for IP addresses.
{
IPv4 = Poco::Net::Impl::IPAddressImpl::IPv4
#ifdef POCO_HAVE_IPv6
,IPv6 = Poco::Net::Impl::IPAddressImpl::IPv6
// The following declarations keep the Family type
// backwards compatible with the previously used
// enum declaration.
typedef AddressFamily::Family Family;
static const Family IPv4 = AddressFamily::IPv4;
#if defined(POCO_HAVE_IPv6)
static const Family IPv6 = AddressFamily::IPv6;
#endif
};
IPAddress();
/// Creates a wildcard (zero) IPv4 IPAddress.
@ -371,13 +372,15 @@ private:
#endif
Ptr pImpl() const;
void newIPv4();
void newIPv4(const void* hostAddr);
void newIPv4(unsigned prefix);
#if defined(POCO_HAVE_IPv6)
void newIPv6();
void newIPv6(const void* hostAddr);
void newIPv6(const void* hostAddr, Poco::UInt32 scope);
void newIPv4(unsigned prefix);
void newIPv6(unsigned prefix);
void newIPv4();
void newIPv6();
#endif
void destruct();
#ifdef POCO_HAVE_ALIGNMENT
@ -394,7 +397,11 @@ private:
AlignerType aligner;
}
#else // !POCO_ENABLE_CPP11
AlignedCharArrayUnion <Poco::Net::Impl::IPv6AddressImpl>
#if defined(POCO_HAVE_IPv6)
AlignedCharArrayUnion <Poco::Net::Impl::IPv6AddressImpl>
#else
AlignedCharArrayUnion <Poco::Net::Impl::IPv4AddressImpl>
#endif
#endif // POCO_ENABLE_CPP11
_memory;
#else // !POCO_HAVE_ALIGNMENT
@ -406,6 +413,8 @@ private:
//
// inlines
//
inline void IPAddress::destruct()
{
#ifdef POCO_HAVE_ALIGNMENT
@ -425,6 +434,16 @@ inline IPAddress::Ptr IPAddress::pImpl() const
}
inline void IPAddress::newIPv4()
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::IPv4AddressImpl;
#else
_pImpl = new Poco::Net::Impl::IPv4AddressImpl;
#endif
}
inline void IPAddress::newIPv4(const void* hostAddr)
{
#ifdef POCO_HAVE_ALIGNMENT
@ -435,6 +454,29 @@ inline void IPAddress::newIPv4(const void* hostAddr)
}
inline void IPAddress::newIPv4(unsigned prefix)
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::IPv4AddressImpl(prefix);
#else
_pImpl = new Poco::Net::Impl::IPv4AddressImpl(prefix);
#endif
}
#if defined(POCO_HAVE_IPv6)
inline void IPAddress::newIPv6()
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::IPv6AddressImpl;
#else
_pImpl = new Poco::Net::Impl::IPv6AddressImpl;
#endif
}
inline void IPAddress::newIPv6(const void* hostAddr)
{
#ifdef POCO_HAVE_ALIGNMENT
@ -455,16 +497,6 @@ inline void IPAddress::newIPv6(const void* hostAddr, Poco::UInt32 scope)
}
inline void IPAddress::newIPv4(unsigned prefix)
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::IPv4AddressImpl(prefix);
#else
_pImpl = new Poco::Net::Impl::IPv4AddressImpl(prefix);
#endif
}
inline void IPAddress::newIPv6(unsigned prefix)
{
#ifdef POCO_HAVE_ALIGNMENT
@ -475,24 +507,7 @@ inline void IPAddress::newIPv6(unsigned prefix)
}
inline void IPAddress::newIPv4()
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::IPv4AddressImpl;
#else
_pImpl = new Poco::Net::Impl::IPv4AddressImpl;
#endif
}
inline void IPAddress::newIPv6()
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::IPv6AddressImpl;
#else
_pImpl = new Poco::Net::Impl::IPv6AddressImpl;
#endif
}
#endif // POCO_HAVE_IPv6
#ifdef POCO_HAVE_ALIGNMENT
@ -503,11 +518,12 @@ inline char* IPAddress::storage()
#endif
BinaryWriter& operator << (BinaryWriter& writer, const IPAddress& value);
BinaryReader& operator >> (BinaryReader& reader, IPAddress& value);
} } // namespace Poco::Net
Net_API Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value);
Net_API Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value);
Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr);
#endif // Net_IPAddress_INCLUDED

View File

@ -37,14 +37,7 @@ class IPAddressImpl
#endif
{
public:
enum Family
/// Possible address families for IP addresses.
{
IPv4
#ifdef POCO_HAVE_IPv6
,IPv6
#endif
};
typedef AddressFamily::Family Family;
virtual ~IPAddressImpl();
@ -129,6 +122,9 @@ private:
};
#if defined(POCO_HAVE_IPv6)
//
// IPv6AddressImpl
//
@ -179,6 +175,9 @@ private:
};
#endif // POCO_HAVE_IPv6
} } } // namespace Poco::Net::Impl

View File

@ -145,6 +145,11 @@ public:
/// appended to result, enclosed in double-quotes.
/// Otherwise, the value is appended to result as-is.
static void decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset = "UTF-8");
static std::string decodeWord(const std::string& text, const std::string& charset = "UTF-8");
/// Decode RFC2047 string.
private:
enum Limits
/// Limits for basic sanity checks when reading a header

View File

@ -39,9 +39,16 @@ class Net_API MulticastSocket: public DatagramSocket
{
public:
MulticastSocket();
/// Creates the multicast socket.
/// Creates an unconnected, unbound multicast socket.
///
/// Before the multicast socket can be used, bind(),
/// bind6() or connect() must be called.
///
/// Notice: The behavior of this constructor has changed
/// in release 2.0. Previously, the constructor created
/// an unbound IPv4 multicast socket.
explicit MulticastSocket(IPAddress::Family family);
explicit MulticastSocket(SocketAddress::Family family);
/// Creates an unconnected datagram socket.
///
/// The socket will be created for the

View File

@ -34,7 +34,7 @@ class Net_API NTPClient
public:
mutable Poco::BasicEvent<NTPEventArgs> response;
explicit NTPClient(IPAddress::Family family, int timeout = 3000000);
explicit NTPClient(SocketAddress::Family family, int timeout = 3000000);
/// Creates an NTP client.
~NTPClient();
@ -53,7 +53,7 @@ public:
/// Returns the number of valid replies.
private:
mutable IPAddress::Family _family;
mutable SocketAddress::Family _family;
int _timeout;
};

View File

@ -51,6 +51,7 @@ POCO_DECLARE_EXCEPTION(Net_API, NTPException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, HTMLFormException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, WebSocketException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, UnsupportedFamilyException, NetException)
POCO_DECLARE_EXCEPTION(Net_API, AddressFamilyMismatchException, NetException)
} } // namespace Poco::Net

View File

@ -248,8 +248,7 @@ public:
/// Returns the NetworkInterface for the given interface index.
///
/// Throws an InterfaceNotFoundException if an interface
/// with the given index does not exist (or IPv6 is not
/// available).
/// with the given index does not exist.
static List list(bool ipOnly = true, bool upOnly = true);
/// Returns a list with all network interfaces

View File

@ -34,7 +34,7 @@ public:
RawSocket();
/// Creates an unconnected IPv4 raw socket.
RawSocket(IPAddress::Family family, int proto = IPPROTO_RAW);
RawSocket(SocketAddress::Family family, int proto = IPPROTO_RAW);
/// Creates an unconnected raw socket.
///
/// The socket will be created for the
@ -80,6 +80,20 @@ public:
///
/// Calls to connect() cannot come before calls to bind().
void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
/// Bind a local address to the socket.
///
/// This is usually only done when establishing a server
/// socket.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
///
/// Calls to connect() cannot come before calls to bind().
int sendBytes(const void* buffer, int length, int flags = 0);
/// Sends the contents of the given buffer through
/// the socket.

View File

@ -33,7 +33,7 @@ public:
RawSocketImpl();
/// Creates an unconnected IPv4 raw socket with IPPROTO_RAW.
RawSocketImpl(IPAddress::Family family, int proto = IPPROTO_RAW);
RawSocketImpl(SocketAddress::Family family, int proto = IPPROTO_RAW);
/// Creates an unconnected raw socket.
///
/// The socket will be created for the

View File

@ -80,6 +80,19 @@ public:
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
/// Binds a local address to the socket.
///
/// This is usually only done when establishing a server
/// socket. TCP clients should not bind a socket to a
/// specific address.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reuseAddress is true, sets the SO_REUSEPORT
/// socket option.
virtual void bind(Poco::UInt16 port, bool reuseAddress = false);
/// Binds a local port to the socket.
///
@ -89,6 +102,18 @@ public:
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
virtual void bind(Poco::UInt16 port, bool reuseAddress, bool reusePort);
/// Binds a local port to the socket.
///
/// This is usually only done when establishing a server
/// socket.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
/// Binds a local IPv6 address to the socket.
///
@ -106,6 +131,26 @@ public:
/// If the library has not been built with IPv6 support,
/// a Poco::NotImplementedException will be thrown.
virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only);
/// Binds a local IPv6 address to the socket.
///
/// This is usually only done when establishing a server
/// socket. TCP clients should not bind a socket to a
/// specific address.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
///
/// The given address must be an IPv6 address. The
/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
/// according to the ipV6Only parameter.
///
/// If the library has not been built with IPv6 support,
/// a Poco::NotImplementedException will be thrown.
virtual void bind6(Poco::UInt16 port, bool reuseAddress = false, bool ipV6Only = false);
/// Binds a local IPv6 port to the socket.
///
@ -122,6 +167,24 @@ public:
/// If the library has not been built with IPv6 support,
/// a Poco::NotImplementedException will be thrown.
virtual void bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only);
/// Binds a local IPv6 port to the socket.
///
/// This is usually only done when establishing a server
/// socket.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
/// The given address must be an IPv6 address. The
/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
/// according to the ipV6Only parameter.
///
/// If the library has not been built with IPv6 support,
/// a Poco::NotImplementedException will be thrown.
virtual void listen(int backlog = 64);
/// Puts the socket into listening state.
///

View File

@ -20,9 +20,14 @@
#include "Poco/Net/Net.h"
#include "Poco/Net/SocketAddressImpl.h"
#include <ostream>
namespace Poco {
class BinaryReader;
class BinaryWriter;
namespace Net {
@ -36,9 +41,25 @@ class Net_API SocketAddress
/// host address and a port number.
{
public:
// The following declarations keep the Family type
// backwards compatible with the previously used
// enum declaration.
typedef AddressFamily::Family Family;
static const Family IPv4 = AddressFamily::IPv4;
#if defined(POCO_HAVE_IPv6)
static const Family IPv6 = AddressFamily::IPv6;
#endif
#if defined(POCO_OS_FAMILY_UNIX)
static const Family UNIX_LOCAL = AddressFamily::UNIX_LOCAL;
#endif
SocketAddress();
/// Creates a wildcard (all zero) IPv4 SocketAddress.
explicit SocketAddress(Family family);
/// Creates a SocketAddress with unspecified (wildcard) IP address
/// of the given family.
SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber);
/// Creates a SocketAddress from an IP address and given port number.
@ -46,12 +67,27 @@ public:
/// Creates a SocketAddress with unspecified (wildcard) IP address
/// and given port number.
SocketAddress(Family family, Poco::UInt16 port);
/// Creates a SocketAddress with unspecified (wildcard) IP address
/// of the given family, and given port number.
SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber);
/// Creates a SocketAddress from an IP address and given port number.
///
/// The IP address must either be a domain name, or it must
/// be in dotted decimal (IPv4) or hex string (IPv6) format.
SocketAddress(Family family, const std::string& hostAddress, Poco::UInt16 portNumber);
/// Creates a SocketAddress from an IP address and given port number.
///
/// The IP address must either be a domain name, or it must
/// be in dotted decimal (IPv4) or hex string (IPv6) format.
///
/// If a domain name is given in hostAddress, it is resolved and the address
/// matching the given family is used. If no address matching the given family
/// is found, or the IP address given in hostAddress does not match the given
/// family, an AddressFamilyMismatchException is thrown.
SocketAddress(const std::string& hostAddress, const std::string& portNumber);
/// Creates a SocketAddress from an IP address and the
/// service name or port number.
@ -62,6 +98,21 @@ public:
/// The given port must either be a decimal port number, or
/// a service name.
SocketAddress(Family family, const std::string& hostAddress, const std::string& portNumber);
/// Creates a SocketAddress from an IP address and the
/// service name or port number.
///
/// The IP address must either be a domain name, or it must
/// be in dotted decimal (IPv4) or hex string (IPv6) format.
///
/// The given port must either be a decimal port number, or
/// a service name.
///
/// If a domain name is given in hostAddress, it is resolved and the address
/// matching the given family is used. If no address matching the given family
/// is found, or the IP address given in hostAddress does not match the given
/// family, an AddressFamilyMismatchException is thrown.
explicit SocketAddress(const std::string& hostAndPort);
/// Creates a SocketAddress from an IP address or host name and the
/// port number/service name. Host name/address and port number must
@ -72,6 +123,17 @@ public:
/// 192.168.1.10:80
/// [::ffff:192.168.1.120]:2040
/// www.appinf.com:8080
///
/// On POSIX platforms supporting UNIX_LOCAL sockets, hostAndPort
/// can also be the absolute path of a local socket, starting with a
/// slash, e.g. "/tmp/local.socket".
SocketAddress(Family family, const std::string& addr);
/// Creates a SocketAddress of the given family from a
/// string representation of the address, which is
/// either an IP address and port number, separated by
/// a colon for IPv4 or IPv6 addresses, or a path for
/// UNIX_LOCAL sockets.
SocketAddress(const SocketAddress& addr);
/// Creates a SocketAddress by copying another one.
@ -103,7 +165,7 @@ public:
std::string toString() const;
/// Returns a string representation of the address.
IPAddress::Family family() const;
Family family() const;
/// Returns the address family of the host's address.
bool operator < (const SocketAddress& socketAddress) const;
@ -113,7 +175,9 @@ public:
enum
{
MAX_ADDRESS_LENGTH =
#if defined(POCO_HAVE_IPv6)
#if defined(POCO_OS_FAMILY_UNIX)
sizeof(struct sockaddr_un)
#elif defined(POCO_HAVE_IPv6)
sizeof(struct sockaddr_in6)
#else
sizeof(struct sockaddr_in)
@ -124,6 +188,9 @@ public:
protected:
void init(const IPAddress& hostAddress, Poco::UInt16 portNumber);
void init(const std::string& hostAddress, Poco::UInt16 portNumber);
void init(Family family, const std::string& hostAddress, Poco::UInt16 portNumber);
void init(Family family, const std::string& address);
void init(const std::string& hostAndPort);
Poco::UInt16 resolveService(const std::string& service);
private:
@ -137,14 +204,18 @@ private:
Ptr pImpl() const;
void newIPv4();
void newIPv4(const sockaddr_in*);
void newIPv4(const IPAddress& hostAddress, Poco::UInt16 portNumber);
#if defined(POCO_HAVE_IPv6)
void newIPv6(const sockaddr_in6*);
void newIPv6(const IPAddress& hostAddress, Poco::UInt16 portNumber);
#endif
#if defined(POCO_OS_FAMILY_UNIX)
void newLocal(const sockaddr_un* sockAddr);
void newLocal(const std::string& path);
#endif
void destruct();
@ -161,7 +232,11 @@ private:
AlignerType aligner;
}
#else // !POCO_ENABLE_CPP11
AlignedCharArrayUnion <Poco::Net::Impl::IPv6SocketAddressImpl>
#if defined(POCO_HAVE_IPv6)
AlignedCharArrayUnion <Poco::Net::Impl::IPv6SocketAddressImpl>
#else
AlignedCharArrayUnion <Poco::Net::Impl::IPv4SocketAddressImpl>
#endif
#endif // POCO_ENABLE_CPP11
_memory;
#else // !POCO_HAVE_ALIGNMENT
@ -224,7 +299,7 @@ inline void SocketAddress::newIPv4(const IPAddress& hostAddress, Poco::UInt16 po
}
#if defined(POCO_HAVE_IPv6)
inline void SocketAddress::newIPv6(const sockaddr_in6* sockAddr)
{
#ifdef POCO_HAVE_ALIGNMENT
@ -243,14 +318,31 @@ inline void SocketAddress::newIPv6(const IPAddress& hostAddress, Poco::UInt16 po
_pImpl = new Poco::Net::Impl::IPv6SocketAddressImpl(hostAddress.addr(), htons(portNumber), hostAddress.scope());
#endif
}
#endif // POCO_HAVE_IPv6
inline IPAddress::Family SocketAddress::family() const
#if defined(POCO_OS_FAMILY_UNIX)
inline void SocketAddress::newLocal(const sockaddr_un* sockAddr)
{
return host().family();
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::LocalSocketAddressImpl(sockAddr);
#else
_pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(sockAddr);
#endif
}
inline void SocketAddress::newLocal(const std::string& path)
{
#ifdef POCO_HAVE_ALIGNMENT
new (storage()) Poco::Net::Impl::LocalSocketAddressImpl(path.c_str());
#else
_pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(path.c_str());
#endif
}
#endif // POCO_OS_FAMILY_UNIX
#ifdef POCO_HAVE_ALIGNMENT
inline char* SocketAddress::storage()
{
@ -259,19 +351,29 @@ inline char* SocketAddress::storage()
#endif
inline bool SocketAddress::operator == (const SocketAddress& socketAddress) const
inline bool SocketAddress::operator == (const SocketAddress& socketAddress) const
{
return host() == socketAddress.host() && port() == socketAddress.port();
#if defined(POCO_OS_FAMILY_UNIX)
if (family() == UNIX_LOCAL)
return toString() == socketAddress.toString();
else
#endif
return host() == socketAddress.host() && port() == socketAddress.port();
}
inline bool SocketAddress::operator != (const SocketAddress& socketAddress) const
{
return host() != socketAddress.host() || port() != socketAddress.port();
return !(operator == (socketAddress));
}
} } // namespace Poco::Net
Net_API Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value);
Net_API Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value);
Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address);
#endif // Net_SocketAddress_INCLUDED

View File

@ -37,6 +37,8 @@ class Net_API SocketAddressImpl
#endif
{
public:
typedef AddressFamily::Family Family;
virtual ~SocketAddressImpl();
virtual IPAddress host() const = 0;
@ -44,6 +46,8 @@ public:
virtual poco_socklen_t length() const = 0;
virtual const struct sockaddr* addr() const = 0;
virtual int af() const = 0;
virtual Family family() const = 0;
virtual std::string toString() const = 0;
protected:
SocketAddressImpl();
@ -65,7 +69,7 @@ public:
poco_socklen_t length() const;
const struct sockaddr* addr() const;
int af() const;
IPAddress::Family family() const;
Family family() const;
std::string toString() const;
private:
@ -107,6 +111,12 @@ inline int IPv4SocketAddressImpl::af() const
}
inline SocketAddressImpl::Family IPv4SocketAddressImpl::family() const
{
return AddressFamily::IPv4;
}
#if defined(POCO_HAVE_IPv6)
@ -121,6 +131,8 @@ public:
poco_socklen_t length() const;
const struct sockaddr* addr() const;
int af() const;
Family family() const;
std::string toString() const;
private:
struct sockaddr_in6 _addr;
@ -161,7 +173,87 @@ inline int IPv6SocketAddressImpl::af() const
}
#endif //POCO_HAVE_IPv6
inline SocketAddressImpl::Family IPv6SocketAddressImpl::family() const
{
return AddressFamily::IPv6;
}
#endif // POCO_HAVE_IPv6
#if defined(POCO_OS_FAMILY_UNIX)
class Net_API LocalSocketAddressImpl: public SocketAddressImpl
{
public:
LocalSocketAddressImpl(const struct sockaddr_un* addr);
LocalSocketAddressImpl(const char* path);
~LocalSocketAddressImpl();
IPAddress host() const;
UInt16 port() const;
poco_socklen_t length() const;
const struct sockaddr* addr() const;
int af() const;
Family family() const;
const char* path() const;
std::string toString() const;
private:
struct sockaddr_un* _pAddr;
// Note: We allocate struct sockaddr_un on the heap, otherwise we would
// waste a lot of memory due to small object optimization in SocketAddress.
};
//
// inlines
//
inline IPAddress LocalSocketAddressImpl::host() const
{
throw Poco::InvalidAccessException("local socket address does not have host IP address");
}
inline UInt16 LocalSocketAddressImpl::port() const
{
throw Poco::InvalidAccessException("local socket address does not have port number");
}
inline poco_socklen_t LocalSocketAddressImpl::length() const
{
return sizeof(struct sockaddr_un);
}
inline const struct sockaddr* LocalSocketAddressImpl::addr() const
{
return reinterpret_cast<const struct sockaddr*>(_pAddr);
}
inline int LocalSocketAddressImpl::af() const
{
return _pAddr->sun_family;
}
inline SocketAddressImpl::Family LocalSocketAddressImpl::family() const
{
return AddressFamily::UNIX_LOCAL;
}
inline const char* LocalSocketAddressImpl::path() const
{
return _pAddr->sun_path;
}
#endif // POCO_OS_FAMILY_UNIX
} } } // namespace Poco::Net::Impl

View File

@ -132,6 +132,7 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#if POCO_OS != POCO_OS_HPUX
#include <sys/select.h>
@ -269,15 +270,19 @@
#if defined(POCO_HAVE_SALEN)
#define poco_set_sa_len(pSA, len) (pSA)->sa_len = (len)
#define poco_set_sin_len(pSA) (pSA)->sin_len = sizeof(struct sockaddr_in)
#define poco_set_sa_len(pSA, len) (pSA)->sa_len = (len)
#define poco_set_sin_len(pSA) (pSA)->sin_len = sizeof(struct sockaddr_in)
#if defined(POCO_HAVE_IPv6)
#define poco_set_sin6_len(pSA) (pSA)->sin6_len = sizeof(struct sockaddr_in6)
#endif
#if defined(POCO_OS_FAMILY_UNIX)
#define poco_set_sun_len(pSA, len) (pSA)->sun_len = (len)
#endif
#else
#define poco_set_sa_len(pSA, len) (void) 0
#define poco_set_sin_len(pSA) (void) 0
#define poco_set_sin6_len(pSA) (void) 0
#define poco_set_sa_len(pSA, len) (void) 0
#define poco_set_sin_len(pSA) (void) 0
#define poco_set_sin6_len(pSA) (void) 0
#define poco_set_sun_len(pSA, len) (void) 0
#endif
@ -346,4 +351,32 @@
#endif
namespace Poco {
namespace Net {
struct AddressFamily
/// AddressFamily::Family replaces the previously used IPAddress::Family
/// enumeration and is now used for IPAddress::Family and SocketAddress::Family.
{
enum Family
/// Possible address families for socket addresses.
{
IPv4,
/// IPv4 address family.
#if defined(POCO_HAVE_IPv6)
IPv6,
/// IPv6 address family.
#endif
#if defined(POCO_OS_FAMILY_UNIX)
UNIX_LOCAL
/// UNIX domain socket address family. Available on UNIX/POSIX platforms only.
#endif
};
};
} } // namespace Poco::Net
#endif // Net_SocketDefs_INCLUDED

View File

@ -84,6 +84,19 @@ public:
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort );
/// Bind a local address to the socket.
///
/// This is usually only done when establishing a server
/// socket. TCP clients should not bind a socket to a
/// specific address.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
/// Bind a local IPv6 address to the socket.
///
@ -101,6 +114,26 @@ public:
/// If the library has not been built with IPv6 support,
/// a Poco::NotImplementedException will be thrown.
virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only);
/// Bind a local IPv6 address to the socket.
///
/// This is usually only done when establishing a server
/// socket. TCP clients should not bind a socket to a
/// specific address.
///
/// If reuseAddress is true, sets the SO_REUSEADDR
/// socket option.
///
/// If reusePort is true, sets the SO_REUSEPORT
/// socket option.
///
/// The given address must be an IPv6 address. The
/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
/// according to the ipV6Only parameter.
///
/// If the library has not been built with IPv6 support,
/// a Poco::NotImplementedException will be thrown.
virtual void listen(int backlog = 64);
/// Puts the socket into listening state.
///
@ -419,11 +452,10 @@ private:
SocketImpl& operator = (const SocketImpl&);
poco_socket_t _sockfd;
#if defined(POCO_BROKEN_TIMEOUTS)
Poco::Timespan _recvTimeout;
Poco::Timespan _sndTimeout;
#endif
bool _blocking;
bool _isBrokenTimeout;
friend class Socket;
friend class SecureSocketImpl;

View File

@ -45,7 +45,7 @@ public:
/// Creates a stream socket and connects it to
/// the socket specified by address.
explicit StreamSocket(IPAddress::Family family);
explicit StreamSocket(SocketAddress::Family family);
/// Creates an unconnected stream socket
/// for the given address family.
///
@ -158,7 +158,7 @@ public:
StreamSocket(SocketImpl* pImpl);
/// Creates the Socket and attaches the given SocketImpl.
/// The socket takes owership of the SocketImpl.
/// The socket takes ownership of the SocketImpl.
///
/// The SocketImpl must be a StreamSocketImpl, otherwise
/// an InvalidArgumentException will be thrown.

View File

@ -33,7 +33,7 @@ public:
StreamSocketImpl();
/// Creates a StreamSocketImpl.
explicit StreamSocketImpl(IPAddress::Family addressFamily);
explicit StreamSocketImpl(SocketAddress::Family addressFamily);
/// Creates a SocketImpl, with the underlying
/// socket initialized for the given address family.

View File

@ -22,6 +22,8 @@
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerParams.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include "Poco/Runnable.h"
#include "Poco/Thread.h"
#include "Poco/ThreadPool.h"
@ -32,6 +34,35 @@ namespace Net {
class TCPServerDispatcher;
class StreamSocket;
class Net_API TCPServerConnectionFilter: public Poco::RefCountedObject
/// A TCPServerConnectionFilter can be used to reject incoming connections
/// before passing them on to the TCPServerDispatcher and
/// starting a thread to handle them.
///
/// An example use case is white-list or black-list IP address filtering.
///
/// Subclasses must override the accept() method.
{
public:
typedef Poco::AutoPtr<TCPServerConnectionFilter> Ptr;
virtual bool accept(const StreamSocket& socket) = 0;
/// Returns true if the given StreamSocket connection should
/// be handled, and passed on to the TCPServerDispatcher.
///
/// Returns false if the socket should be closed immediately.
///
/// The socket can be prevented from being closed immediately
/// if false is returned by creating a copy of the socket.
/// This can be used to handle certain socket connections in
/// a special way, outside the TCPServer framework.
protected:
virtual ~TCPServerConnectionFilter();
};
class Net_API TCPServer: public Poco::Runnable
@ -164,6 +195,19 @@ public:
Poco::UInt16 port() const;
/// Returns the port the server socket listens on.
void setConnectionFilter(const TCPServerConnectionFilter::Ptr& pFilter);
/// Sets a TCPServerConnectionFilter. Can also be used to remove
/// a filter by passing a null pointer.
///
/// To avoid a potential race condition, the filter must
/// be set before the TCPServer is started. Trying to set
/// the filter after start() has been called will trigger
/// an assertion.
TCPServerConnectionFilter::Ptr getConnectionFilter() const;
/// Returns the TCPServerConnectionFilter set with setConnectionFilter(),
/// or null pointer if no filter has been set.
protected:
void run();
/// Runs the server. The server will run until
@ -179,10 +223,11 @@ private:
TCPServer(const TCPServer&);
TCPServer& operator = (const TCPServer&);
ServerSocket _socket;
ServerSocket _socket;
TCPServerDispatcher* _pDispatcher;
Poco::Thread _thread;
bool _stopped;
TCPServerConnectionFilter::Ptr _pConnectionFilter;
Poco::Thread _thread;
bool _stopped;
};
@ -201,6 +246,12 @@ inline Poco::UInt16 TCPServer::port() const
}
inline TCPServerConnectionFilter::Ptr TCPServer::getConnectionFilter() const
{
return _pConnectionFilter;
}
} } // namespace Poco::Net

View File

@ -21,6 +21,7 @@
#include "Poco/Net/Net.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Buffer.h"
namespace Poco {
@ -219,6 +220,21 @@ public:
/// The frame flags and opcode (FrameFlags and FrameOpcodes)
/// is stored in flags.
int receiveFrame(Poco::Buffer<char>& buffer, int& flags);
/// Receives a frame from the socket and stores it
/// after any previous content in buffer.
///
/// Returns the number of bytes received.
/// A return value of 0 means that the peer has
/// shut down or closed the connection.
///
/// Throws a TimeoutException if a receive timeout has
/// been set and nothing is received within that interval.
/// Throws a NetException (or a subclass) in case of other errors.
///
/// The frame flags and opcode (FrameFlags and FrameOpcodes)
/// is stored in flags.
Mode mode() const;
/// Returns WS_SERVER if the WebSocket is a server-side
/// WebSocket, or WS_CLIENT otherwise.

View File

@ -19,6 +19,7 @@
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Buffer.h"
#include "Poco/Random.h"
#include "Poco/Buffer.h"
@ -45,12 +46,17 @@ public:
virtual int receiveBytes(void* buffer, int length, int flags);
/// Receives a WebSocket protocol frame.
virtual int receiveBytes(Poco::Buffer<char>& buffer, int flags);
/// Receives a WebSocket protocol frame.
virtual SocketImpl* acceptConnection(SocketAddress& clientAddr);
virtual void connect(const SocketAddress& address);
virtual void connect(const SocketAddress& address, const Poco::Timespan& timeout);
virtual void connectNB(const SocketAddress& address);
virtual void bind(const SocketAddress& address, bool reuseAddress = false);
virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only);
virtual void listen(int backlog = 64);
virtual void close();
virtual void shutdownReceive();
@ -80,6 +86,8 @@ protected:
MAX_HEADER_LENGTH = 14
};
int receiveHeader(char mask[4], bool& useMask);
int receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask);
int receiveNBytes(void* buffer, int bytes);
int receiveSomeBytes(char* buffer, int bytes);
virtual ~WebSocketImpl();

View File

@ -29,7 +29,7 @@ DatagramSocket::DatagramSocket(): Socket(new DatagramSocketImpl)
}
DatagramSocket::DatagramSocket(IPAddress::Family family): Socket(new DatagramSocketImpl(family))
DatagramSocket::DatagramSocket(SocketAddress::Family family): Socket(new DatagramSocketImpl(family))
{
}
@ -81,6 +81,12 @@ void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress)
}
void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort)
{
impl()->bind(address, reuseAddress, reusePort);
}
int DatagramSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);

View File

@ -25,17 +25,20 @@ namespace Net {
DatagramSocketImpl::DatagramSocketImpl()
{
init(AF_INET);
}
DatagramSocketImpl::DatagramSocketImpl(IPAddress::Family family)
DatagramSocketImpl::DatagramSocketImpl(SocketAddress::Family family)
{
if (family == IPAddress::IPv4)
if (family == SocketAddress::IPv4)
init(AF_INET);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
else if (family == SocketAddress::IPv6)
init(AF_INET6);
#endif
#if defined(POCO_OS_FAMILY_UNIX)
else if (family == SocketAddress::UNIX_LOCAL)
init(AF_UNIX);
#endif
else throw InvalidArgumentException("Invalid or unsupported address family passed to DatagramSocketImpl");
}

View File

@ -44,7 +44,8 @@ HTTPClientSession::HTTPClientSession():
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@ -56,7 +57,8 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@ -68,7 +70,8 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@ -80,7 +83,8 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port)
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@ -92,7 +96,8 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port,
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
_expectResponseBody(false),
_responseReceived(false)
{
}
@ -190,9 +195,10 @@ std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
{
clearException();
_pResponseStream = 0;
_responseReceived = false;
bool keepAlive = getKeepAlive();
if ((connected() && !keepAlive) || mustReconnect())
if (((connected() && !keepAlive) || mustReconnect()) && !_host.empty())
{
close();
_mustReconnect = false;
@ -203,7 +209,7 @@ std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
reconnect();
if (!keepAlive)
request.setKeepAlive(false);
if (!request.has(HTTPRequest::HOST))
if (!request.has(HTTPRequest::HOST) && !_host.empty())
request.setHost(_host, _port);
if (!_proxyConfig.host.empty() && !bypassProxy())
{
@ -258,25 +264,28 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
_pRequestStream = 0;
if (networkException()) networkException()->rethrow();
do
if (!_responseReceived)
{
response.clear();
HTTPHeaderInputStream his(*this);
try
do
{
response.read(his);
}
catch (Exception&)
{
close();
if (networkException())
networkException()->rethrow();
else
response.clear();
HTTPHeaderInputStream his(*this);
try
{
response.read(his);
}
catch (Exception&)
{
close();
if (networkException())
networkException()->rethrow();
else
throw;
throw;
throw;
}
}
while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
}
while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
_mustReconnect = getKeepAlive() && !response.getKeepAlive();
@ -297,6 +306,34 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
}
bool HTTPClientSession::peekResponse(HTTPResponse& response)
{
poco_assert (!_responseReceived);
_pRequestStream->flush();
if (networkException()) networkException()->rethrow();
response.clear();
HTTPHeaderInputStream his(*this);
try
{
response.read(his);
}
catch (Exception&)
{
close();
if (networkException())
networkException()->rethrow();
else
throw;
throw;
}
_responseReceived = response.getStatus() != HTTPResponse::HTTP_CONTINUE;
return !_responseReceived;
}
void HTTPClientSession::reset()
{
close();

View File

@ -41,6 +41,7 @@ const std::string HTTPRequest::COOKIE = "Cookie";
const std::string HTTPRequest::AUTHORIZATION = "Authorization";
const std::string HTTPRequest::PROXY_AUTHORIZATION = "Proxy-Authorization";
const std::string HTTPRequest::UPGRADE = "Upgrade";
const std::string HTTPRequest::EXPECT = "Expect";
HTTPRequest::HTTPRequest():
@ -257,4 +258,20 @@ void HTTPRequest::setCredentials(const std::string& header, const std::string& s
}
bool HTTPRequest::getExpectContinue() const
{
const std::string& expect = get(EXPECT, EMPTY);
return !expect.empty() && icompare(expect, "100-continue") == 0;
}
void HTTPRequest::setExpectContinue(bool expectContinue)
{
if (expectContinue)
set(EXPECT, "100-continue");
else
erase(EXPECT);
}
} } // namespace Poco::Net

View File

@ -38,6 +38,7 @@ namespace Net {
const std::string HTTPResponse::HTTP_REASON_CONTINUE = "Continue";
const std::string HTTPResponse::HTTP_REASON_SWITCHING_PROTOCOLS = "Switching Protocols";
const std::string HTTPResponse::HTTP_REASON_PROCESSING = "Processing";
const std::string HTTPResponse::HTTP_REASON_OK = "OK";
const std::string HTTPResponse::HTTP_REASON_CREATED = "Created";
const std::string HTTPResponse::HTTP_REASON_ACCEPTED = "Accepted";
@ -45,13 +46,17 @@ const std::string HTTPResponse::HTTP_REASON_NONAUTHORITATIVE = "N
const std::string HTTPResponse::HTTP_REASON_NO_CONTENT = "No Content";
const std::string HTTPResponse::HTTP_REASON_RESET_CONTENT = "Reset Content";
const std::string HTTPResponse::HTTP_REASON_PARTIAL_CONTENT = "Partial Content";
const std::string HTTPResponse::HTTP_REASON_MULTI_STATUS = "Multi Status";
const std::string HTTPResponse::HTTP_REASON_ALREADY_REPORTED = "Already Reported";
const std::string HTTPResponse::HTTP_REASON_IM_USED = "IM Used";
const std::string HTTPResponse::HTTP_REASON_MULTIPLE_CHOICES = "Multiple Choices";
const std::string HTTPResponse::HTTP_REASON_MOVED_PERMANENTLY = "Moved Permanently";
const std::string HTTPResponse::HTTP_REASON_FOUND = "Found";
const std::string HTTPResponse::HTTP_REASON_SEE_OTHER = "See Other";
const std::string HTTPResponse::HTTP_REASON_NOT_MODIFIED = "Not Modified";
const std::string HTTPResponse::HTTP_REASON_USEPROXY = "Use Proxy";
const std::string HTTPResponse::HTTP_REASON_USE_PROXY = "Use Proxy";
const std::string HTTPResponse::HTTP_REASON_TEMPORARY_REDIRECT = "Temporary Redirect";
const std::string HTTPResponse::HTTP_REASON_PERMANENT_REDIRECT = "Permanent Redirect";
const std::string HTTPResponse::HTTP_REASON_BAD_REQUEST = "Bad Request";
const std::string HTTPResponse::HTTP_REASON_UNAUTHORIZED = "Unauthorized";
const std::string HTTPResponse::HTTP_REASON_PAYMENT_REQUIRED = "Payment Required";
@ -65,17 +70,33 @@ const std::string HTTPResponse::HTTP_REASON_CONFLICT = "C
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_REQUEST_ENTITY_TOO_LARGE = "Request Entity Too Large";
const std::string HTTPResponse::HTTP_REASON_REQUEST_URI_TOO_LONG = "Request-URI Too Large";
const std::string HTTPResponse::HTTP_REASON_UNSUPPORTED_MEDIA_TYPE = "Unsupported Media Type";
const std::string HTTPResponse::HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE = "Requested Range Not Satisfiable";
const std::string HTTPResponse::HTTP_REASON_EXPECTATION_FAILED = "Expectation Failed";
const std::string HTTPResponse::HTTP_REASON_IM_A_TEAPOT = "I'm a Teapot";
const std::string HTTPResponse::HTTP_REASON_ENCHANCE_YOUR_CALM = "Enchance Your Calm";
const std::string HTTPResponse::HTTP_REASON_MISDIRECTED_REQUEST = "Misdirected Request";
const std::string HTTPResponse::HTTP_REASON_UNPROCESSABLE_ENTITY = "Unprocessable Entity";
const std::string HTTPResponse::HTTP_REASON_LOCKED = "Locked";
const std::string HTTPResponse::HTTP_REASON_FAILED_DEPENDENCY = "Failed Dependency";
const std::string HTTPResponse::HTTP_REASON_UPGRADE_REQUIRED = "Upgrade Required";
const std::string HTTPResponse::HTTP_REASON_PRECONDITION_REQUIRED = "Precondition Required";
const std::string HTTPResponse::HTTP_REASON_TOO_MANY_REQUESTS = "Too Many Requests";
const std::string HTTPResponse::HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE = "Request Header Fields Too Large";
const std::string HTTPResponse::HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS = "Unavailable For Legal Reasons";
const std::string HTTPResponse::HTTP_REASON_INTERNAL_SERVER_ERROR = "Internal Server Error";
const std::string HTTPResponse::HTTP_REASON_NOT_IMPLEMENTED = "Not Implemented";
const std::string HTTPResponse::HTTP_REASON_BAD_GATEWAY = "Bad Gateway";
const std::string HTTPResponse::HTTP_REASON_SERVICE_UNAVAILABLE = "Service Unavailable";
const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-out";
const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version not supported";
const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-Out";
const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version Not Supported";
const std::string HTTPResponse::HTTP_REASON_VARIANT_ALSO_NEGOTIATES = "Variant Also Negotiates";
const std::string HTTPResponse::HTTP_REASON_INSUFFICIENT_STORAGE = "Insufficient Storage";
const std::string HTTPResponse::HTTP_REASON_LOOP_DETECTED = "Loop Detected";
const std::string HTTPResponse::HTTP_REASON_NOT_EXTENDED = "Not Extended";
const std::string HTTPResponse::HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED = "Network Authentication Required";
const std::string HTTPResponse::HTTP_REASON_UNKNOWN = "???";
const std::string HTTPResponse::DATE = "Date";
const std::string HTTPResponse::SET_COOKIE = "Set-Cookie";
@ -238,6 +259,8 @@ const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
return HTTP_REASON_CONTINUE;
case HTTP_SWITCHING_PROTOCOLS:
return HTTP_REASON_SWITCHING_PROTOCOLS;
case HTTP_PROCESSING:
return HTTP_REASON_PROCESSING;
case HTTP_OK:
return HTTP_REASON_OK;
case HTTP_CREATED:
@ -252,6 +275,12 @@ const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
return HTTP_REASON_RESET_CONTENT;
case HTTP_PARTIAL_CONTENT:
return HTTP_REASON_PARTIAL_CONTENT;
case HTTP_MULTI_STATUS:
return HTTP_REASON_MULTI_STATUS;
case HTTP_ALREADY_REPORTED:
return HTTP_REASON_ALREADY_REPORTED;
case HTTP_IM_USED:
return HTTP_REASON_IM_USED;
case HTTP_MULTIPLE_CHOICES:
return HTTP_REASON_MULTIPLE_CHOICES;
case HTTP_MOVED_PERMANENTLY:
@ -262,8 +291,8 @@ const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
return HTTP_REASON_SEE_OTHER;
case HTTP_NOT_MODIFIED:
return HTTP_REASON_NOT_MODIFIED;
case HTTP_USEPROXY:
return HTTP_REASON_USEPROXY;
case HTTP_USE_PROXY:
return HTTP_REASON_USE_PROXY;
case HTTP_TEMPORARY_REDIRECT:
return HTTP_REASON_TEMPORARY_REDIRECT;
case HTTP_BAD_REQUEST:
@ -292,16 +321,38 @@ const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
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_REQUEST_ENTITY_TOO_LARGE:
return HTTP_REASON_REQUEST_ENTITY_TOO_LARGE;
case HTTP_REQUEST_URI_TOO_LONG:
return HTTP_REASON_REQUEST_URI_TOO_LONG;
case HTTP_UNSUPPORTED_MEDIA_TYPE:
return HTTP_REASON_UNSUPPORTED_MEDIA_TYPE;
case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
return HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE;
case HTTP_EXPECTATION_FAILED:
return HTTP_REASON_EXPECTATION_FAILED;
case HTTP_IM_A_TEAPOT:
return HTTP_REASON_IM_A_TEAPOT;
case HTTP_ENCHANCE_YOUR_CALM:
return HTTP_REASON_ENCHANCE_YOUR_CALM;
case HTTP_MISDIRECTED_REQUEST:
return HTTP_REASON_MISDIRECTED_REQUEST;
case HTTP_UNPROCESSABLE_ENTITY:
return HTTP_REASON_UNPROCESSABLE_ENTITY;
case HTTP_LOCKED:
return HTTP_REASON_LOCKED;
case HTTP_FAILED_DEPENDENCY:
return HTTP_REASON_FAILED_DEPENDENCY;
case HTTP_UPGRADE_REQUIRED:
return HTTP_REASON_UPGRADE_REQUIRED;
case HTTP_PRECONDITION_REQUIRED:
return HTTP_REASON_PRECONDITION_REQUIRED;
case HTTP_TOO_MANY_REQUESTS:
return HTTP_REASON_TOO_MANY_REQUESTS;
case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE:
return HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE;
case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
return HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS;
case HTTP_INTERNAL_SERVER_ERROR:
return HTTP_REASON_INTERNAL_SERVER_ERROR;
case HTTP_NOT_IMPLEMENTED:
@ -314,6 +365,16 @@ const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
return HTTP_REASON_GATEWAY_TIMEOUT;
case HTTP_VERSION_NOT_SUPPORTED:
return HTTP_REASON_VERSION_NOT_SUPPORTED;
case HTTP_VARIANT_ALSO_NEGOTIATES:
return HTTP_REASON_VARIANT_ALSO_NEGOTIATES;
case HTTP_INSUFFICIENT_STORAGE:
return HTTP_REASON_INSUFFICIENT_STORAGE;
case HTTP_LOOP_DETECTED:
return HTTP_REASON_LOOP_DETECTED;
case HTTP_NOT_EXTENDED:
return HTTP_REASON_NOT_EXTENDED;
case HTTP_NETWORK_AUTHENTICATION_REQUIRED:
return HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED;
default:
return HTTP_REASON_UNKNOWN;
}

View File

@ -83,7 +83,7 @@ void HTTPServerConnection::run()
#endif
if (pHandler.get())
{
if (request.expectContinue())
if (request.getExpectContinue() && response.getStatus() == HTTPResponse::HTTP_OK)
response.sendContinue();
pHandler->handleRequest(request, response);

View File

@ -20,6 +20,7 @@
#include "Poco/Net/HTTPFixedLengthStream.h"
#include "Poco/Net/HTTPChunkedStream.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/String.h"
@ -30,9 +31,6 @@ namespace Poco {
namespace Net {
const std::string HTTPServerRequestImpl::EXPECT("Expect");
HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponseImpl& response, HTTPServerSession& session, HTTPServerParams* pParams):
_response(response),
_session(session),
@ -69,6 +67,12 @@ HTTPServerRequestImpl::~HTTPServerRequestImpl()
}
bool HTTPServerRequestImpl::secure() const
{
return _session.socket().secure();
}
StreamSocket& HTTPServerRequestImpl::socket()
{
return _session.socket();
@ -81,11 +85,4 @@ StreamSocket HTTPServerRequestImpl::detachSocket()
}
bool HTTPServerRequestImpl::expectContinue() const
{
const std::string& expect = get(EXPECT, EMPTY);
return !expect.empty() && icompare(expect, "100-continue") == 0;
}
} } // namespace Poco::Net

View File

@ -30,7 +30,9 @@ HTTPSession::HTTPSession():
_pCurrent(0),
_pEnd(0),
_keepAlive(false),
_timeout(HTTP_DEFAULT_TIMEOUT),
_connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT),
_receiveTimeout(HTTP_DEFAULT_TIMEOUT),
_sendTimeout(HTTP_DEFAULT_TIMEOUT),
_pException(0)
{
}
@ -42,7 +44,9 @@ HTTPSession::HTTPSession(const StreamSocket& socket):
_pCurrent(0),
_pEnd(0),
_keepAlive(false),
_timeout(HTTP_DEFAULT_TIMEOUT),
_connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT),
_receiveTimeout(HTTP_DEFAULT_TIMEOUT),
_sendTimeout(HTTP_DEFAULT_TIMEOUT),
_pException(0)
{
}
@ -54,7 +58,9 @@ HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive):
_pCurrent(0),
_pEnd(0),
_keepAlive(keepAlive),
_timeout(HTTP_DEFAULT_TIMEOUT),
_connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT),
_receiveTimeout(HTTP_DEFAULT_TIMEOUT),
_sendTimeout(HTTP_DEFAULT_TIMEOUT),
_pException(0)
{
}
@ -89,7 +95,15 @@ void HTTPSession::setKeepAlive(bool keepAlive)
void HTTPSession::setTimeout(const Poco::Timespan& timeout)
{
_timeout = timeout;
setTimeout(timeout, timeout, timeout);
}
void HTTPSession::setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout)
{
_connectionTimeout = connectionTimeout;
_sendTimeout = sendTimeout;
_receiveTimeout = receiveTimeout;
}
@ -179,8 +193,9 @@ bool HTTPSession::connected() const
void HTTPSession::connect(const SocketAddress& address)
{
_socket.connect(address, _timeout);
_socket.setReceiveTimeout(_timeout);
_socket.connect(address, _connectionTimeout);
_socket.setReceiveTimeout(_receiveTimeout);
_socket.setSendTimeout(_sendTimeout);
_socket.setNoDelay(true);
// There may be leftover data from a previous (failed) request in the buffer,
// so we clear it.

View File

@ -140,7 +140,7 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
{
return new HTTPResponseStream(rs, pSession);
}
else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry)
else if (res.getStatus() == HTTPResponse::HTTP_USE_PROXY && !retry)
{
// The requested resource MUST be accessed through the proxy
// given by the Location field. The Location field gives the

View File

@ -34,7 +34,7 @@ namespace Poco {
namespace Net {
ICMPClient::ICMPClient(IPAddress::Family family):
ICMPClient::ICMPClient(SocketAddress::Family family):
_family(family)
{
}

View File

@ -33,13 +33,25 @@ using Poco::UInt16;
using Poco::UInt32;
using Poco::Net::Impl::IPAddressImpl;
using Poco::Net::Impl::IPv4AddressImpl;
#if defined(POCO_HAVE_IPv6)
using Poco::Net::Impl::IPv6AddressImpl;
#endif
namespace Poco {
namespace Net {
#if !defined(_MSC_VER) || defined(__STDC__)
// Go home MSVC, you're drunk...
// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members
const IPAddress::Family IPAddress::IPv4;
#if defined(POCO_HAVE_IPv6)
const IPAddress::Family IPAddress::IPv6;
#endif
#endif
IPAddress::IPAddress()
{
newIPv4();
@ -50,8 +62,10 @@ IPAddress::IPAddress(const IPAddress& addr)
{
if (addr.family() == IPv4)
newIPv4(addr.addr());
#if defined(POCO_HAVE_IPv6)
else
newIPv6(addr.addr(), addr.scope());
#endif
}
@ -63,8 +77,7 @@ IPAddress::IPAddress(Family family)
else if (family == IPv6)
newIPv6();
#endif
else
throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
}
@ -219,8 +232,12 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
destruct();
if (addr.family() == IPAddress::IPv4)
newIPv4(addr.addr());
else
#if defined(POCO_HAVE_IPv6)
else if (addr.family() == IPAddress::IPv6)
newIPv6(addr.addr(), addr.scope());
#endif
else
throw Poco::InvalidArgumentException("Invalid or unsupported address family");
}
return *this;
}
@ -228,7 +245,7 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
IPAddress::Family IPAddress::family() const
{
return static_cast<IPAddress::Family>(pImpl()->family());
return pImpl()->family();
}
@ -561,19 +578,30 @@ IPAddress IPAddress::broadcast()
}
BinaryWriter& operator << (BinaryWriter& writer, const IPAddress& value)
} } // namespace Poco::Net
Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value)
{
writer.stream().write((const char*) value.addr(), value.length());
writer << static_cast<Poco::UInt8>(value.length());
writer.writeRaw(reinterpret_cast<const char*>(value.addr()), value.length());
return writer;
}
BinaryReader& operator >> (BinaryReader& reader, IPAddress& value)
Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value)
{
char buf[sizeof(struct in6_addr)];
reader.stream().read(buf, value.length());
value = IPAddress(buf, value.length());
Poco::UInt8 length;
reader >> length;
reader.readRaw(buf, length);
value = Poco::Net::IPAddress(buf, length);
return reader;
}
} } // namespace Poco::Net
std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr)
{
ostr << addr.toString();
return ostr;
}

View File

@ -143,7 +143,7 @@ const void* IPv4AddressImpl::addr() const
IPAddressImpl::Family IPv4AddressImpl::family() const
{
return IPAddressImpl::IPv4;
return AddressFamily::IPv4;
}
@ -500,7 +500,7 @@ const void* IPv6AddressImpl::addr() const
IPAddressImpl::Family IPv6AddressImpl::family() const
{
return IPAddressImpl::IPv6;
return AddressFamily::IPv6;
}
@ -535,6 +535,8 @@ unsigned IPv6AddressImpl::prefixLength() const
throw NotImplementedException("prefixLength() not implemented");
#endif
}
Poco::UInt32 IPv6AddressImpl::scope() const
{
return _scope;

View File

@ -16,6 +16,11 @@
#include "Poco/Net/NetException.h"
#include "Poco/String.h"
#include "Poco/Ascii.h"
#include "Poco/TextConverter.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Base64Decoder.h"
#include "Poco/UTF8Encoding.h"
#include <sstream>
namespace Poco {
@ -96,7 +101,7 @@ void MessageHeader::read(std::istream& istr)
throw MessageException("Folded field value too long/no CRLF found");
}
Poco::trimRightInPlace(value);
add(name, value);
add(name, decodeWord(value));
++fields;
}
istr.putback(ch);
@ -252,4 +257,138 @@ void MessageHeader::quote(const std::string& value, std::string& result, bool al
}
void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset_to)
{
std::string tempout;
StringTokenizer tokens(ins, "?");
std::string charset = toUpper(tokens[0]);
std::string encoding = toUpper(tokens[1]);
std::string text = tokens[2];
std::istringstream istr(text);
if (encoding == "B")
{
// Base64 encoding.
Base64Decoder decoder(istr);
for (char c; decoder.get(c); tempout += c) {}
}
else if (encoding == "Q")
{
// Quoted encoding.
for (char c; istr.get(c);)
{
if (c == '_')
{
//RFC 2047 _ is a space.
tempout += " ";
continue;
}
// FIXME: check that we have enought chars-
if (c == '=')
{
// The next two chars are hex representation of the complete byte.
std::string hex;
for (int i = 0; i < 2; i++)
{
istr.get(c);
hex += c;
}
hex = toUpper(hex);
tempout += (char)(int)strtol(hex.c_str(), 0, 16);
continue;
}
tempout += c;
}
}
else
{
// Wrong encoding
outs = ins;
return;
}
// convert to the right charset.
if (charset != charset_to)
{
try
{
TextEncoding& enc = TextEncoding::byName(charset);
TextEncoding& dec = TextEncoding::byName(charset_to);
TextConverter converter(enc, dec);
converter.convert(tempout, outs);
}
catch (...)
{
// FIXME: Unsuported encoding...
outs = tempout;
}
}
else
{
// Not conversion necesary.
outs = tempout;
}
}
std::string MessageHeader::decodeWord(const std::string& text, const std::string& charset)
{
std::string outs, tmp = text;
do {
std::string tmp2;
// find the begining of the next rfc2047 chunk
size_t pos = tmp.find("=?");
if (pos == std::string::npos) {
// No more found, return
outs += tmp;
break;
}
// check if there are standar text before the rfc2047 chunk, and if so, copy it.
if (pos > 0) {
outs += tmp.substr(0, pos);
}
// remove text already copied.
tmp = tmp.substr(pos + 2);
// find the first separator
size_t pos1 = tmp.find("?");
if (pos1 == std::string::npos) {
// not found.
outs += tmp;
break;
}
// find the second separator
size_t pos2 = tmp.find("?", pos1 + 1);
if (pos2 == std::string::npos) {
// not found
outs += tmp;
break;
}
// find the end of the actual rfc2047 chunk
size_t pos3 = tmp.find("?=", pos2 + 1);
if (pos3 == std::string::npos) {
// not found.
outs += tmp;
break;
}
// At this place, there are a valid rfc2047 chunk, so decode and copy the result.
decodeRFC2047(tmp.substr(0, pos3), tmp2, charset);
outs += tmp2;
// Jump at the rest of the string and repeat the whole process.
tmp = tmp.substr(pos3 + 2);
} while (true);
return outs;
}
} } // namespace Poco::Net

View File

@ -51,8 +51,12 @@ MulticastSocket::MulticastSocket()
}
MulticastSocket::MulticastSocket(IPAddress::Family family): DatagramSocket(family)
MulticastSocket::MulticastSocket(SocketAddress::Family family): DatagramSocket(family)
{
#if defined(POCO_OS_FAMILY_UNIX)
if (family == SocketAddress::UNIX_LOCAL)
throw Poco::InvalidArgumentException("Cannot create a MulticastSocket with UNIX_LOCAL socket");
#endif
}
@ -80,18 +84,17 @@ MulticastSocket& MulticastSocket::operator = (const Socket& socket)
void MulticastSocket::setInterface(const NetworkInterface& interfc)
{
if (address().family() == IPAddress::IPv4)
if (address().family() == SocketAddress::IPv4)
{
impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.firstAddress(IPAddress::IPv4));
}
#if defined(POCO_HAVE_IPv6)
else if (address().family() == IPAddress::IPv6)
else if (address().family() == SocketAddress::IPv6)
{
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interfc.index());
}
#endif
else
throw UnsupportedFamilyException("Unknown or unsupported socket family.");
else throw UnsupportedFamilyException("Unknown or unsupported socket family.");
}

View File

@ -47,7 +47,8 @@ POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception")
POCO_IMPLEMENT_EXCEPTION(NTPException, NetException, "NTP Exception")
POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception")
POCO_IMPLEMENT_EXCEPTION(WebSocketException, NetException, "WebSocket Exception")
POCO_IMPLEMENT_EXCEPTION(UnsupportedFamilyException, NetException, "Unknown or unsupported socket family.")
POCO_IMPLEMENT_EXCEPTION(UnsupportedFamilyException, NetException, "Unknown or unsupported socket family")
POCO_IMPLEMENT_EXCEPTION(AddressFamilyMismatchException, NetException, "Address family mismatch")
} } // namespace Poco::Net

View File

@ -242,7 +242,7 @@ void NetworkInterfaceImpl::setPhyParams()
#if !defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_VXWORKS)
struct ifreq ifr;
std::strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
DatagramSocket ds;
DatagramSocket ds(SocketAddress::IPv4);
ds.impl()->ioctl(SIOCGIFFLAGS, &ifr);
setFlags(ifr.ifr_flags);
@ -796,16 +796,10 @@ bool NetworkInterface::isUp() const
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{
Map map = NetworkInterface::map(false, false);
Map::const_iterator it = map.begin();
Map::const_iterator end = map.end();
for (; it != end; ++it)
{
if (it->second.name() == name && ((requireIPv6 && it->second.supportsIPv6()) || !requireIPv6))
return it->second;
}
throw InterfaceNotFoundException(name);
if (requireIPv6)
return forName(name, IPv6_ONLY);
else
return forName(name, IPv4_OR_IPv6);
}

View File

@ -30,7 +30,7 @@ RawSocket::RawSocket():
}
RawSocket::RawSocket(IPAddress::Family family, int proto):
RawSocket::RawSocket(SocketAddress::Family family, int proto):
Socket(new RawSocketImpl(family, proto))
{
}
@ -84,6 +84,12 @@ void RawSocket::bind(const SocketAddress& address, bool reuseAddress)
}
void RawSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort)
{
impl()->bind(address, reuseAddress, reusePort);
}
int RawSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);

View File

@ -29,12 +29,12 @@ RawSocketImpl::RawSocketImpl()
}
RawSocketImpl::RawSocketImpl(IPAddress::Family family, int proto)
RawSocketImpl::RawSocketImpl(SocketAddress::Family family, int proto)
{
if (family == IPAddress::IPv4)
if (family == SocketAddress::IPv4)
init2(AF_INET, proto);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
else if (family == SocketAddress::IPv6)
init2(AF_INET6, proto);
#endif
else throw InvalidArgumentException("Invalid or unsupported address family passed to RawSocketImpl");

View File

@ -78,6 +78,12 @@ void ServerSocket::bind(const SocketAddress& address, bool reuseAddress)
}
void ServerSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort)
{
impl()->bind(address, reuseAddress, reusePort);
}
void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress)
{
IPAddress wildcardAddr;
@ -86,17 +92,47 @@ void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress)
}
void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress, bool reusePort)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, reuseAddress, reusePort);
}
void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
{
impl()->bind6(address, reuseAddress, ipV6Only);
}
void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only)
{
impl()->bind6(address, reuseAddress, reusePort, ipV6Only);
}
void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only)
{
#if defined(POCO_HAVE_IPv6)
IPAddress wildcardAddr(IPAddress::IPv6);
SocketAddress address(wildcardAddr, port);
impl()->bind6(address, reuseAddress, ipV6Only);
#else
throw Poco::NotImplementedException("No IPv6 support available");
#endif // POCO_HAVE_IPv6
}
void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only)
{
#if defined(POCO_HAVE_IPv6)
IPAddress wildcardAddr(IPAddress::IPv6);
SocketAddress address(wildcardAddr, port);
impl()->bind6(address, reuseAddress, reusePort, ipV6Only);
#else
throw Poco::NotImplementedException("No IPv6 support available");
#endif // POCO_HAVE_IPv6
}

View File

@ -22,9 +22,6 @@
#elif defined(POCO_HAVE_FD_POLL)
#include "Poco/SharedPtr.h"
#include <poll.h>
typedef Poco::SharedPtr<pollfd,
Poco::ReferenceCounter,
Poco::ReleaseArrayPolicy<pollfd> > SharedPollArray;
#endif
@ -209,6 +206,7 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
return readList.size() + writeList.size() + exceptList.size();
#elif defined(POCO_HAVE_FD_POLL)
typedef Poco::SharedPtr<pollfd, Poco::ReferenceCounter, Poco::ReleaseArrayPolicy<pollfd> > SharedPollArray;
nfds_t nfd = readList.size() + writeList.size() + exceptList.size();
if (0 == nfd) return 0;

View File

@ -18,19 +18,24 @@
#include "Poco/Net/DNS.h"
#include "Poco/RefCountedObject.h"
#include "Poco/NumberParser.h"
#include "Poco/NumberFormatter.h"
#include "Poco/BinaryReader.h"
#include "Poco/BinaryWriter.h"
#include <algorithm>
#include <cstring>
using Poco::RefCountedObject;
using Poco::NumberParser;
using Poco::NumberFormatter;
using Poco::UInt16;
using Poco::InvalidArgumentException;
using Poco::Net::Impl::SocketAddressImpl;
using Poco::Net::Impl::IPv4SocketAddressImpl;
#ifdef POCO_HAVE_IPv6
using Poco::Net::Impl::IPv6SocketAddressImpl;
#endif
#ifdef POCO_OS_FAMILY_UNIX
using Poco::Net::Impl::LocalSocketAddressImpl;
#endif
namespace Poco {
@ -51,12 +56,31 @@ struct AFLT
//
#if !defined(_MSC_VER) || defined(__STDC__)
// Go home MSVC, you're drunk...
// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members
const SocketAddress::Family SocketAddress::IPv4;
#if defined(POCO_HAVE_IPv6)
const SocketAddress::Family SocketAddress::IPv6;
#endif
#if defined(POCO_OS_FAMILY_UNIX)
const SocketAddress::Family SocketAddress::UNIX_LOCAL;
#endif
#endif
SocketAddress::SocketAddress()
{
newIPv4();
}
SocketAddress::SocketAddress(Family fam)
{
init(IPAddress(fam), 0);
}
SocketAddress::SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber)
{
init(hostAddress, portNumber);
@ -69,65 +93,76 @@ SocketAddress::SocketAddress(Poco::UInt16 portNumber)
}
SocketAddress::SocketAddress(Family fam, Poco::UInt16 portNumber)
{
init(IPAddress(fam), portNumber);
}
SocketAddress::SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber)
{
init(hostAddress, portNumber);
}
SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber)
{
init(fam, hostAddress, portNumber);
}
SocketAddress::SocketAddress(const std::string& hostAddress, const std::string& portNumber)
{
init(hostAddress, resolveService(portNumber));
}
SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, const std::string& portNumber)
{
init(fam, hostAddress, resolveService(portNumber));
}
SocketAddress::SocketAddress(Family fam, const std::string& addr)
{
init(fam, addr);
}
SocketAddress::SocketAddress(const std::string& hostAndPort)
{
poco_assert (!hostAndPort.empty());
std::string host;
std::string port;
std::string::const_iterator it = hostAndPort.begin();
std::string::const_iterator end = hostAndPort.end();
if (*it == '[')
{
++it;
while (it != end && *it != ']') host += *it++;
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
++it;
}
else
{
while (it != end && *it != ':') host += *it++;
}
if (it != end && *it == ':')
{
++it;
while (it != end) port += *it++;
}
else throw InvalidArgumentException("Missing port number");
init(host, resolveService(port));
init(hostAndPort);
}
SocketAddress::SocketAddress(const SocketAddress& socketAddress)
{
if (socketAddress.family() == IPAddress::IPv4)
if (socketAddress.family() == IPv4)
newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
else
#if defined(POCO_HAVE_IPv6)
else if (socketAddress.family() == IPv6)
newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
#endif
#if defined(POCO_OS_FAMILY_UNIX)
else if (socketAddress.family() == UNIX_LOCAL)
newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr()));
#endif
}
SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length)
{
if (length == sizeof(struct sockaddr_in))
if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET)
newIPv4(reinterpret_cast<const struct sockaddr_in*>(sockAddr));
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct sockaddr_in6))
else if (length == sizeof(struct sockaddr_in6) && sockAddr->sa_family == AF_INET6)
newIPv6(reinterpret_cast<const struct sockaddr_in6*>(sockAddr));
#endif
else throw Poco::InvalidArgumentException("Invalid address length passed to SocketAddress()");
#if defined(POCO_OS_FAMILY_UNIX)
else if (length > 0 && length <= sizeof(struct sockaddr_un) && sockAddr->sa_family == AF_UNIX)
newLocal(reinterpret_cast<const sockaddr_un*>(sockAddr));
#endif
else throw Poco::InvalidArgumentException("Invalid address length or family passed to SocketAddress()");
}
@ -141,6 +176,9 @@ bool SocketAddress::operator < (const SocketAddress& socketAddress) const
{
if (family() < socketAddress.family()) return true;
if (family() > socketAddress.family()) return false;
#if defined(POCO_OS_FAMILY_UNIX)
if (family() == UNIX_LOCAL) return toString() < socketAddress.toString();
#endif
if (host() < socketAddress.host()) return true;
if (host() > socketAddress.host()) return false;
return (port() < socketAddress.port());
@ -152,10 +190,16 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress)
if (&socketAddress != this)
{
destruct();
if (socketAddress.family() == IPAddress::IPv4)
if (socketAddress.family() == IPv4)
newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr()));
else
#if defined(POCO_HAVE_IPv6)
else if (socketAddress.family() == IPv6)
newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr()));
#endif
#if defined(POCO_OS_FAMILY_UNIX)
else if (socketAddress.family() == UNIX_LOCAL)
newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr()));
#endif
}
return *this;
}
@ -191,19 +235,15 @@ int SocketAddress::af() const
}
SocketAddress::Family SocketAddress::family() const
{
return static_cast<Family>(pImpl()->family());
}
std::string SocketAddress::toString() const
{
std::string result;
#if defined(POCO_HAVE_IPv6)
if (host().family() == IPAddress::IPv6)
result.append("[");
result.append(host().toString());
if (host().family() == IPAddress::IPv6)
result.append("]");
#endif
result.append(":");
NumberFormatter::append(result, port());
return result;
return pImpl()->toString();
}
@ -232,7 +272,7 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber
HostEntry::AddressList addresses = he.addresses();
if (addresses.size() > 0)
{
#if defined(POCO_HAVE_IPv6) && !defined(POCO_SOCKETADDRESS_DONT_PREFER_IPV4)
#if defined(POCO_HAVE_IPv6) && defined(POCO_SOCKETADDRESS_PREFER_IPv4)
// if we get both IPv4 and IPv6 addresses, prefer IPv4
std::stable_sort(addresses.begin(), addresses.end(), AFLT());
#endif
@ -243,6 +283,109 @@ void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber
}
void SocketAddress::init(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber)
{
IPAddress ip;
if (IPAddress::tryParse(hostAddress, ip))
{
if (ip.family() != fam) throw AddressFamilyMismatchException(hostAddress);
init(ip, portNumber);
}
else
{
HostEntry he = DNS::hostByName(hostAddress);
HostEntry::AddressList addresses = he.addresses();
if (addresses.size() > 0)
{
for (HostEntry::AddressList::const_iterator it = addresses.begin(); it != addresses.end(); ++it)
{
if (it->family() == fam)
{
init(*it, portNumber);
return;
}
}
throw AddressFamilyMismatchException(hostAddress);
}
else throw HostNotFoundException("No address found for host", hostAddress);
}
}
void SocketAddress::init(Family fam, const std::string& address)
{
#if defined(POCO_OS_FAMILY_UNIX)
if (fam == UNIX_LOCAL)
{
newLocal(address);
}
else
#endif
{
std::string host;
std::string port;
std::string::const_iterator it = address.begin();
std::string::const_iterator end = address.end();
if (*it == '[')
{
++it;
while (it != end && *it != ']') host += *it++;
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
++it;
}
else
{
while (it != end && *it != ':') host += *it++;
}
if (it != end && *it == ':')
{
++it;
while (it != end) port += *it++;
}
else throw InvalidArgumentException("Missing port number");
init(fam, host, resolveService(port));
}
}
void SocketAddress::init(const std::string& hostAndPort)
{
poco_assert (!hostAndPort.empty());
std::string host;
std::string port;
std::string::const_iterator it = hostAndPort.begin();
std::string::const_iterator end = hostAndPort.end();
#if defined(POCO_OS_FAMILY_UNIX)
if (*it == '/')
{
newLocal(hostAndPort);
return;
}
#endif
if (*it == '[')
{
++it;
while (it != end && *it != ']') host += *it++;
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
++it;
}
else
{
while (it != end && *it != ':') host += *it++;
}
if (it != end && *it == ':')
{
++it;
while (it != end) port += *it++;
}
else throw InvalidArgumentException("Missing port number");
init(host, resolveService(port));
}
Poco::UInt16 SocketAddress::resolveService(const std::string& service)
{
unsigned port;
@ -266,3 +409,29 @@ Poco::UInt16 SocketAddress::resolveService(const std::string& service)
} } // namespace Poco::Net
Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value)
{
writer << value.host();
writer << value.port();
return writer;
}
Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value)
{
Poco::Net::IPAddress host;
reader >> host;
Poco::UInt16 port;
reader >> port;
value = Poco::Net::SocketAddress(host, port);
return reader;
}
std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address)
{
ostr << address.toString();
return ostr;
}

View File

@ -14,6 +14,7 @@
#include "Poco/Net/SocketAddressImpl.h"
#include "Poco/Net/SocketDefs.h"
#include "Poco/NumberFormatter.h"
#include <cstring>
@ -60,11 +61,22 @@ IPv4SocketAddressImpl::IPv4SocketAddressImpl(const void* addr, UInt16 port)
{
std::memset(&_addr, 0, sizeof(_addr));
_addr.sin_family = AF_INET;
poco_set_sin_len(&_addr);
std::memcpy(&_addr.sin_addr, addr, sizeof(_addr.sin_addr));
_addr.sin_port = port;
}
std::string IPv4SocketAddressImpl::toString() const
{
std::string result;
result.append(host().toString());
result.append(":");
NumberFormatter::append(result, ntohs(port()));
return result;
}
#if defined(POCO_HAVE_IPv6)
@ -100,7 +112,59 @@ IPv6SocketAddressImpl::IPv6SocketAddressImpl(const void* addr, UInt16 port, UInt
}
std::string IPv6SocketAddressImpl::toString() const
{
std::string result;
result.append("[");
result.append(host().toString());
result.append("]");
result.append(":");
NumberFormatter::append(result, ntohs(port()));
return result;
}
#endif // POCO_HAVE_IPv6
#if defined(POCO_OS_FAMILY_UNIX)
//
// LocalSocketAddressImpl
//
LocalSocketAddressImpl::LocalSocketAddressImpl(const struct sockaddr_un* addr)
{
_pAddr = new sockaddr_un;
std::memcpy(_pAddr, addr, sizeof(struct sockaddr_un));
}
LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path)
{
_pAddr = new sockaddr_un;
poco_set_sun_len(_pAddr, std::strlen(path) + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1);
_pAddr->sun_family = AF_UNIX;
std::strcpy(_pAddr->sun_path, path);
}
LocalSocketAddressImpl::~LocalSocketAddressImpl()
{
delete _pAddr;
}
std::string LocalSocketAddressImpl::toString() const
{
std::string result(path());
return result;
}
#endif // POCO_OS_FAMILY_UNIX
} } } // namespace Poco::Net::Impl

View File

@ -31,6 +31,11 @@
#endif
#ifdef POCO_OS_FAMILY_WINDOWS
#include <Windows.h>
#endif
using Poco::IOException;
using Poco::TimeoutException;
using Poco::InvalidArgumentException;
@ -42,16 +47,34 @@ namespace Poco {
namespace Net {
bool checkIsBrokenTimeout()
{
#if defined(POCO_BROKEN_TIMEOUTS)
return true;
#elif defined(POCO_OS_FAMILY_WINDOWS)
// on Windows 7 and lower, socket timeouts have a minimum of 500ms, use poll for timeouts on this case
// https://social.msdn.microsoft.com/Forums/en-US/76620f6d-22b1-4872-aaf0-833204f3f867/minimum-timeout-value-for-sorcvtimeo
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (GetVersionEx(&vi) == 0) return true; //throw SystemException("Cannot get OS version information");
return vi.dwMajorVersion < 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion < 2);
#endif
return false;
}
SocketImpl::SocketImpl():
_sockfd(POCO_INVALID_SOCKET),
_blocking(true)
_blocking(true),
_isBrokenTimeout(checkIsBrokenTimeout())
{
}
SocketImpl::SocketImpl(poco_socket_t sockfd):
_sockfd(sockfd),
_blocking(true)
_blocking(true),
_isBrokenTimeout(checkIsBrokenTimeout())
{
}
@ -165,16 +188,21 @@ void SocketImpl::connectNB(const SocketAddress& address)
void SocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
bind(address, reuseAddress, true);
}
void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reusePort)
{
if (_sockfd == POCO_INVALID_SOCKET)
{
init(address.af());
}
if (reuseAddress)
{
setReuseAddress(true);
if (reusePort)
setReusePort(true);
}
#if defined(POCO_VXWORKS)
int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length());
#else
@ -185,9 +213,15 @@ void SocketImpl::bind(const SocketAddress& address, bool reuseAddress)
void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
{
bind6(address, reuseAddress, true, ipV6Only);
}
void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only)
{
#if defined(POCO_HAVE_IPv6)
if (address.family() != IPAddress::IPv6)
if (address.family() != SocketAddress::IPv6)
throw Poco::InvalidArgumentException("SocketAddress must be an IPv6 address");
if (_sockfd == POCO_INVALID_SOCKET)
@ -200,10 +234,9 @@ void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV
if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined.");
#endif
if (reuseAddress)
{
setReuseAddress(true);
if (reusePort)
setReusePort(true);
}
int rc = ::bind(_sockfd, address.addr(), address.length());
if (rc != 0) error(address.toString());
#else
@ -260,13 +293,14 @@ void SocketImpl::shutdown()
int SocketImpl::sendBytes(const void* buffer, int length, int flags)
{
#if defined(POCO_BROKEN_TIMEOUTS)
if (_sndTimeout.totalMicroseconds() != 0)
if (_isBrokenTimeout)
{
if (!poll(_sndTimeout, SELECT_WRITE))
throw TimeoutException();
if (_sndTimeout.totalMicroseconds() != 0)
{
if (!poll(_sndTimeout, SELECT_WRITE))
throw TimeoutException();
}
}
#endif
int rc;
do
@ -282,13 +316,14 @@ int SocketImpl::sendBytes(const void* buffer, int length, int flags)
int SocketImpl::receiveBytes(void* buffer, int length, int flags)
{
#if defined(POCO_BROKEN_TIMEOUTS)
if (_recvTimeout.totalMicroseconds() != 0)
if (_isBrokenTimeout)
{
if (!poll(_recvTimeout, SELECT_READ))
throw TimeoutException();
if (_recvTimeout.totalMicroseconds() != 0)
{
if (!poll(_recvTimeout, SELECT_READ))
throw TimeoutException();
}
}
#endif
int rc;
do
@ -331,13 +366,14 @@ int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& addr
int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
#if defined(POCO_BROKEN_TIMEOUTS)
if (_recvTimeout.totalMicroseconds() != 0)
if (_isBrokenTimeout)
{
if (!poll(_recvTimeout, SELECT_READ))
throw TimeoutException();
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);
@ -555,11 +591,11 @@ void SocketImpl::setSendTimeout(const Poco::Timespan& timeout)
#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS)
int value = (int) timeout.totalMilliseconds();
setOption(SOL_SOCKET, SO_SNDTIMEO, value);
#elif defined(POCO_BROKEN_TIMEOUTS)
_sndTimeout = timeout;
#else
#elif !defined(POCO_BROKEN_TIMEOUTS)
setOption(SOL_SOCKET, SO_SNDTIMEO, timeout);
#endif
if (_isBrokenTimeout)
_sndTimeout = timeout;
}
@ -570,11 +606,11 @@ Poco::Timespan SocketImpl::getSendTimeout()
int value;
getOption(SOL_SOCKET, SO_SNDTIMEO, value);
result = Timespan::TimeDiff(value)*1000;
#elif defined(POCO_BROKEN_TIMEOUTS)
result = _sndTimeout;
#else
#elif !defined(POCO_BROKEN_TIMEOUTS)
getOption(SOL_SOCKET, SO_SNDTIMEO, result);
#endif
if (_isBrokenTimeout)
result = _sndTimeout;
return result;
}
@ -588,9 +624,9 @@ void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout)
#else
setOption(SOL_SOCKET, SO_RCVTIMEO, timeout);
#endif
#else
_recvTimeout = timeout;
#endif
if (_isBrokenTimeout)
_recvTimeout = timeout;
}
@ -601,11 +637,11 @@ Poco::Timespan SocketImpl::getReceiveTimeout()
int value;
getOption(SOL_SOCKET, SO_RCVTIMEO, value);
result = Timespan::TimeDiff(value)*1000;
#elif defined(POCO_BROKEN_TIMEOUTS)
result = _recvTimeout;
#else
#elif !defined(POCO_BROKEN_TIMEOUTS)
getOption(SOL_SOCKET, SO_RCVTIMEO, result);
#endif
if (_isBrokenTimeout)
result = _recvTimeout;
return result;
}
@ -1060,6 +1096,8 @@ void SocketImpl::error(int code, const std::string& arg)
throw IOException("Broken pipe", code);
case EBADF:
throw IOException("Bad socket descriptor", code);
case ENOENT:
throw IOException("Not found", arg, code);
#endif
default:
throw IOException(NumberFormatter::format(code), arg, code);

View File

@ -39,7 +39,7 @@ StreamSocket::StreamSocket(const SocketAddress& address): Socket(new StreamSocke
}
StreamSocket::StreamSocket(IPAddress::Family family): Socket(new StreamSocketImpl(family))
StreamSocket::StreamSocket(SocketAddress::Family family): Socket(new StreamSocketImpl(family))
{
}

View File

@ -26,13 +26,17 @@ StreamSocketImpl::StreamSocketImpl()
}
StreamSocketImpl::StreamSocketImpl(IPAddress::Family family)
StreamSocketImpl::StreamSocketImpl(SocketAddress::Family family)
{
if (family == IPAddress::IPv4)
if (family == SocketAddress::IPv4)
init(AF_INET);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
else if (family == SocketAddress::IPv6)
init(AF_INET6);
#endif
#if defined(POCO_OS_FAMILY_UNIX)
else if (family == SocketAddress::UNIX_LOCAL)
init(AF_UNIX);
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to StreamSocketImpl");
}

View File

@ -28,6 +28,21 @@ namespace Poco {
namespace Net {
//
// TCPServerConnectionFilter
//
TCPServerConnectionFilter::~TCPServerConnectionFilter()
{
}
//
// TCPServer
//
TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber, TCPServerParams::Ptr pParams):
_socket(ServerSocket(portNumber)),
_thread(threadName(_socket)),
@ -120,9 +135,18 @@ void TCPServer::run()
try
{
StreamSocket ss = _socket.acceptConnection();
// enabe nodelay per default: OSX really needs that
ss.setNoDelay(true);
_pDispatcher->enqueue(ss);
if (!_pConnectionFilter || _pConnectionFilter->accept(ss))
{
// enable nodelay per default: OSX really needs that
#if defined(POCO_OS_FAMILY_UNIX)
if (ss.address().family() != AddressFamily::UNIX_LOCAL)
#endif
{
ss.setNoDelay(true);
}
_pDispatcher->enqueue(ss);
}
}
catch (Poco::Exception& exc)
{
@ -191,6 +215,14 @@ int TCPServer::refusedConnections() const
}
void TCPServer::setConnectionFilter(const TCPServerConnectionFilter::Ptr& pConnectionFilter)
{
poco_assert (_stopped);
_pConnectionFilter = pConnectionFilter;
}
std::string TCPServer::threadName(const ServerSocket& socket)
{
#if _WIN32_WCE == 0x0800

View File

@ -19,7 +19,6 @@
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPServerSession.h"
#include "Poco/Net/NetException.h"
#include "Poco/Buffer.h"
#include "Poco/MemoryStream.h"
#include "Poco/NullStream.h"
#include "Poco/BinaryWriter.h"
@ -113,6 +112,14 @@ int WebSocket::receiveFrame(void* buffer, int length, int& flags)
}
int WebSocket::receiveFrame(Poco::Buffer<char>& buffer, int& flags)
{
int n = static_cast<WebSocketImpl*>(impl())->receiveBytes(buffer, 0);
flags = static_cast<WebSocketImpl*>(impl())->frameFlags();
return n;
}
WebSocket::Mode WebSocket::mode() const
{
return static_cast<WebSocketImpl*>(impl())->mustMaskPayload() ? WS_CLIENT : WS_SERVER;

View File

@ -106,7 +106,7 @@ int WebSocketImpl::sendBytes(const void* buffer, int length, int flags)
}
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
int WebSocketImpl::receiveHeader(char mask[4], bool& useMask)
{
char header[MAX_HEADER_LENGTH];
int n = receiveNBytes(header, 2);
@ -116,82 +116,101 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
return n;
}
poco_assert (n == 2);
Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]);
int maskOffset = 0;
if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4;
lengthByte &= 0x7f;
if (lengthByte > 0 || maskOffset > 0)
{
if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH)
{
n = receiveNBytes(header + 2, lengthByte + maskOffset);
}
else
{
n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2);
}
if (n <= 0) throw WebSocketException("Incomplete header received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
n += 2;
}
Poco::MemoryInputStream istr(header, n);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt8 flags;
char mask[4];
reader >> flags >> lengthByte;
Poco::UInt8 flags = static_cast<Poco::UInt8>(header[0]);
_frameFlags = flags;
int payloadLength = 0;
int payloadOffset = 2;
if ((lengthByte & 0x7f) == 127)
Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]);
useMask = ((lengthByte & FRAME_FLAG_MASK) != 0);
int payloadLength;
lengthByte &= 0x7f;
if (lengthByte == 127)
{
n = receiveNBytes(header + 2, 8);
if (n <= 0)
{
_frameFlags = 0;
return n;
}
Poco::MemoryInputStream istr(header + 2, 8);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt64 l;
reader >> l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 8;
}
else if ((lengthByte & 0x7f) == 126)
else if (lengthByte == 126)
{
n = receiveNBytes(header + 2, 2);
if (n <= 0)
{
_frameFlags = 0;
return n;
}
Poco::MemoryInputStream istr(header + 2, 2);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt16 l;
reader >> l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 2;
}
else
{
Poco::UInt8 l = lengthByte & 0x7f;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadLength = lengthByte;
}
if (lengthByte & FRAME_FLAG_MASK)
if (useMask)
{
reader.readRaw(mask, 4);
payloadOffset += 4;
n = receiveNBytes(mask, 4);
if (n <= 0)
{
_frameFlags = 0;
return n;
}
}
int received = 0;
if (payloadOffset < n)
return payloadLength;
}
int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask)
{
int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength);
if (received <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
if (useMask)
{
std::memcpy(buffer, header + payloadOffset, n - payloadOffset);
received = n - payloadOffset;
}
if (received < payloadLength)
{
n = receiveNBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received);
if (n <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
received += n;
}
if (lengthByte & FRAME_FLAG_MASK)
{
char* p = reinterpret_cast<char*>(buffer);
for (int i = 0; i < received; i++)
{
p[i] ^= mask[i % 4];
buffer[i] ^= mask[i % 4];
}
}
return received;
}
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
{
char mask[4];
bool useMask;
int payloadLength = receiveHeader(mask, useMask);
if (payloadLength <= 0)
return payloadLength;
if (payloadLength > length)
throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
return receivePayload(reinterpret_cast<char*>(buffer), payloadLength, mask, useMask);
}
int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int)
{
char mask[4];
bool useMask;
int payloadLength = receiveHeader(mask, useMask);
if (payloadLength <= 0)
return payloadLength;
int oldSize = buffer.size();
buffer.resize(oldSize + payloadLength);
return receivePayload(buffer.begin() + oldSize, payloadLength, mask, useMask);
}
int WebSocketImpl::receiveNBytes(void* buffer, int bytes)
{
int received = receiveSomeBytes(reinterpret_cast<char*>(buffer), bytes);
@ -212,7 +231,7 @@ int WebSocketImpl::receiveNBytes(void* buffer, int bytes)
int WebSocketImpl::receiveSomeBytes(char* buffer, int bytes)
{
int n = static_cast<int>(_buffer.size() - _bufferOffset);
int n = _buffer.size() - _bufferOffset;
if (n > 0)
{
if (bytes < n) n = bytes;
@ -257,12 +276,24 @@ void WebSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
}
void WebSocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reusePort)
{
throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl");
}
void WebSocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
{
throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl");
}
void WebSocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only)
{
throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl");
}
void WebSocketImpl::listen(int backlog)
{
throw Poco::InvalidAccessException("Cannot listen() on a WebSocketImpl");

View File

@ -37,20 +37,20 @@ DNSTest::~DNSTest()
void DNSTest::testHostByName()
{
HostEntry he1 = DNS::hostByName("aliastest.appinf.com");
HostEntry he1 = DNS::hostByName("aliastest.pocoproject.org");
// different systems report different canonical names, unfortunately.
assert (he1.name() == "dnstest.appinf.com" || he1.name() == "aliastest.appinf.com");
assert (he1.name() == "dnstest.pocoproject.org" || he1.name() == "aliastest.pocoproject.org");
#if !defined(POCO_HAVE_ADDRINFO)
// getaddrinfo() does not report any aliases
assert (!he1.aliases().empty());
assert (he1.aliases()[0] == "aliastest.appinf.com");
assert (he1.aliases()[0] == "aliastest.pocoproject.org");
#endif
assert (he1.addresses().size() >= 1);
assert (he1.addresses()[0].toString() == "1.2.3.4");
try
{
HostEntry he1 = DNS::hostByName("nohost.appinf.com");
HostEntry he1 = DNS::hostByName("nohost.pocoproject.org");
fail("host not found - must throw");
}
catch (HostNotFoundException&)

View File

@ -49,7 +49,7 @@ void DatagramSocketTest::testEcho()
UDPEchoServer echoServer;
DatagramSocket ss;
char buffer[256];
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
int n = ss.sendBytes("hello", 5);
assert (n == 5);
n = ss.receiveBytes(buffer, sizeof(buffer));
@ -61,9 +61,9 @@ void DatagramSocketTest::testEcho()
void DatagramSocketTest::testSendToReceiveFrom()
{
UDPEchoServer echoServer(SocketAddress("localhost", 0));
DatagramSocket ss;
int n = ss.sendTo("hello", 5, SocketAddress("localhost", echoServer.port()));
UDPEchoServer echoServer(SocketAddress("127.0.0.1", 0));
DatagramSocket ss(SocketAddress::IPv4);
int n = ss.sendTo("hello", 5, SocketAddress("127.0.0.1", echoServer.port()));
assert (n == 5);
char buffer[256];
SocketAddress sa;
@ -76,6 +76,21 @@ void DatagramSocketTest::testSendToReceiveFrom()
}
void DatagramSocketTest::testUnbound()
{
UDPEchoServer echoServer;
DatagramSocket ss;
char buffer[256];
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
int n = ss.sendBytes("hello", 5);
assert (n == 5);
n = ss.receiveBytes(buffer, sizeof(buffer));
assert (n == 5);
assert (std::string(buffer, n) == "hello");
ss.close();
}
void DatagramSocketTest::testBroadcast()
{
UDPEchoServer echoServer;
@ -134,6 +149,7 @@ CppUnit::Test* DatagramSocketTest::suite()
CppUnit_addTest(pSuite, DatagramSocketTest, testEcho);
CppUnit_addTest(pSuite, DatagramSocketTest, testSendToReceiveFrom);
CppUnit_addTest(pSuite, DatagramSocketTest, testUnbound);
#if (POCO_OS != POCO_OS_FREE_BSD) // works only with local net bcast and very randomly
CppUnit_addTest(pSuite, DatagramSocketTest, testBroadcast);
#endif

View File

@ -26,6 +26,7 @@ public:
void testEcho();
void testSendToReceiveFrom();
void testUnbound();
void testBroadcast();
void setUp();

View File

@ -35,7 +35,7 @@ void DialogSocketTest::testDialogSocket()
{
EchoServer echoServer;
DialogSocket ds;
ds.connect(SocketAddress("localhost", echoServer.port()));
ds.connect(SocketAddress("127.0.0.1", echoServer.port()));
ds.sendMessage("Hello, world!");
std::string str;

View File

@ -30,6 +30,16 @@ EchoServer::EchoServer():
}
EchoServer::EchoServer(const Poco::Net::SocketAddress& address):
_socket(address),
_thread("EchoServer"),
_stop(false)
{
_thread.start(*this);
_ready.wait();
}
EchoServer::~EchoServer()
{
_stop = true;

View File

@ -27,6 +27,9 @@ public:
EchoServer();
/// Creates the EchoServer.
EchoServer(const Poco::Net::SocketAddress& address);
/// Creates the EchoServer using the given address.
~EchoServer();
/// Destroys the EchoServer.

View File

@ -92,7 +92,7 @@ void FTPClientSessionTest::testLogin1()
{
DialogServer server;
server.addResponse("220 localhost FTP ready");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
assert (session.isOpen());
assert (!session.isLoggedIn());
login(server, session);
@ -123,7 +123,7 @@ void FTPClientSessionTest::testLogin2()
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
Poco::UInt16 serverPort = server.port();
FTPClientSession session("localhost", serverPort, "user", "password");
FTPClientSession session("127.0.0.1", serverPort, "user", "password");
assert (session.isOpen());
assert (session.isLoggedIn());
server.addResponse("221 Good Bye");
@ -137,7 +137,7 @@ void FTPClientSessionTest::testLogin2()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
session.open("localhost", serverPort, "user", "password");
session.open("127.0.0.1", serverPort, "user", "password");
assert (session.isOpen());
assert (session.isLoggedIn());
server.addResponse("221 Good Bye");
@ -157,7 +157,7 @@ void FTPClientSessionTest::testLogin3()
FTPClientSession session;
assert (!session.isOpen());
assert (!session.isLoggedIn());
session.open("localhost", server.port(), "user", "password");
session.open("127.0.0.1", server.port(), "user", "password");
server.addResponse("221 Good Bye");
session.close();
assert (!session.isOpen());
@ -170,7 +170,7 @@ void FTPClientSessionTest::testLoginFailed1()
{
DialogServer server;
server.addResponse("421 localhost FTP not ready");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
try
{
session.login("user", "password");
@ -190,7 +190,7 @@ void FTPClientSessionTest::testLoginFailed2()
server.addResponse("220 localhost FTP ready");
server.addResponse("331 Password required");
server.addResponse("530 Login incorrect");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
try
{
session.login("user", "password");
@ -211,7 +211,7 @@ void FTPClientSessionTest::testCommands()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.login("user", "password");
std::string cmd = server.popCommand();
assert (cmd == "USER user");
@ -340,7 +340,7 @@ void FTPClientSessionTest::testDownloadPORT()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.setPassive(false);
session.login("user", "password");
server.clearCommands();
@ -371,7 +371,7 @@ void FTPClientSessionTest::testDownloadPORT()
cmd = server.popCommandWait();
assert (cmd == "RETR test.txt");
SocketAddress sa("localhost", (Poco::UInt16) port);
SocketAddress sa("127.0.0.1", (Poco::UInt16) port);
DialogSocket dataSock;
dataSock.connect(sa);
@ -395,7 +395,7 @@ void FTPClientSessionTest::testDownloadEPRT()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.setPassive(false);
session.login("user", "password");
server.clearCommands();
@ -419,7 +419,7 @@ void FTPClientSessionTest::testDownloadEPRT()
cmd = server.popCommandWait();
assert (cmd == "RETR test.txt");
SocketAddress sa("localhost", (Poco::UInt16) port);
SocketAddress sa("127.0.0.1", (Poco::UInt16) port);
DialogSocket dataSock;
dataSock.connect(sa);
@ -443,7 +443,7 @@ void FTPClientSessionTest::testDownloadPASV()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.login("user", "password");
server.clearCommands();
@ -476,7 +476,7 @@ void FTPClientSessionTest::testDownloadEPSV()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.login("user", "password");
server.clearCommands();
@ -511,7 +511,7 @@ void FTPClientSessionTest::testUpload()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.login("user", "password");
server.clearCommands();
@ -544,7 +544,7 @@ void FTPClientSessionTest::testList()
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
FTPClientSession session("localhost", server.port());
FTPClientSession session("127.0.0.1", server.port());
session.login("user", "password");
server.clearCommands();

View File

@ -75,7 +75,7 @@ void FTPStreamFactoryTest::testDownload()
URI uri;
uri.setScheme("ftp");
uri.setHost("localhost");
uri.setHost("127.0.0.1");
uri.setPort(server.port());
uri.setPath("/test.txt;type=a");
FTPStreamFactory sf;
@ -116,7 +116,7 @@ void FTPStreamFactoryTest::testList()
URI uri;
uri.setScheme("ftp");
uri.setHost("localhost");
uri.setHost("127.0.0.1");
uri.setPort(server.port());
uri.setPath("/usr/guest/data;type=d");
FTPStreamFactory sf;
@ -157,7 +157,7 @@ void FTPStreamFactoryTest::testUserInfo()
URI uri;
uri.setScheme("ftp");
uri.setHost("localhost");
uri.setHost("127.0.0.1");
uri.setPort(server.port());
uri.setPath("/test.txt;type=a");
uri.setUserInfo("user:secret");
@ -200,7 +200,7 @@ void FTPStreamFactoryTest::testPasswordProvider()
URI uri;
uri.setScheme("ftp");
uri.setHost("localhost");
uri.setHost("127.0.0.1");
uri.setPort(server.port());
uri.setPath("/test.txt;type=a");
uri.setUserInfo("user");
@ -231,7 +231,7 @@ void FTPStreamFactoryTest::testMissingPasswordProvider()
URI uri;
uri.setScheme("ftp");
uri.setHost("localhost");
uri.setHost("127.0.0.1");
uri.setPort(server.port());
uri.setPath("/test.txt;type=a");
uri.setUserInfo("user");

View File

@ -161,6 +161,29 @@ void HTMLFormTest::testReadUrlGET()
}
void HTMLFormTest::testReadUrlGETMultiple()
{
HTTPRequest req("GET", "/form.cgi?field1=value1&field1=value%202&field1=value%3D3&field1=value%264");
HTMLForm form(req);
assert (form.size() == 4);
HTMLForm::ConstIterator it = form.find("field1");
assert (it != form.end());
assert (it->first == "field1" && it->second == "value1");
++it;
assert (it != form.end());
assert (it->first == "field1" && it->second == "value 2");
++it;
assert (it != form.end());
assert (it->first == "field1" && it->second == "value=3");
++it;
assert (it != form.end());
assert (it->first == "field1" && it->second == "value&4");
++it;
assert (it == form.end());
}
void HTMLFormTest::testReadUrlPOST()
{
HTTPRequest req("POST", "/form.cgi?field0=value0");
@ -293,6 +316,21 @@ void HTMLFormTest::testSubmit3()
}
void HTMLFormTest::testSubmit4()
{
HTMLForm form;
form.add("field1", "value1");
form.add("field1", "value 2");
form.add("field1", "value=3");
form.add("field1", "value&4");
HTTPRequest req("GET", "/form.cgi");
form.prepareSubmit(req);
assert (req.getURI() == "/form.cgi?field1=value1&field1=value%202&field1=value%3D3&field1=value%264");
}
void HTMLFormTest::testFieldLimitUrl()
{
HTTPRequest req("GET", "/form.cgi?field1=value1&field2=value%202&field3=value%3D3&field4=value%264");
@ -369,6 +407,7 @@ CppUnit::Test* HTMLFormTest::suite()
CppUnit_addTest(pSuite, HTMLFormTest, testWriteUrl);
CppUnit_addTest(pSuite, HTMLFormTest, testWriteMultipart);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGET);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGETMultiple);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPOST);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPUT);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlBOM);
@ -376,6 +415,7 @@ CppUnit::Test* HTMLFormTest::suite()
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit1);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit3);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit4);
CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitUrl);
CppUnit_addTest(pSuite, HTMLFormTest, testFieldLimitMultipart);

View File

@ -27,6 +27,7 @@ public:
void testWriteUrl();
void testWriteMultipart();
void testReadUrlGET();
void testReadUrlGETMultiple();
void testReadUrlPOST();
void testReadUrlPUT();
void testReadUrlBOM();
@ -34,6 +35,7 @@ public:
void testSubmit1();
void testSubmit2();
void testSubmit3();
void testSubmit4();
void testFieldLimitUrl();
void testFieldLimitMultipart();

View File

@ -41,7 +41,7 @@ HTTPClientSessionTest::~HTTPClientSessionTest()
void HTTPClientSessionTest::testGetSmall()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/small");
s.sendRequest(request);
HTTPResponse response;
@ -57,7 +57,7 @@ void HTTPClientSessionTest::testGetSmall()
void HTTPClientSessionTest::testGetLarge()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/large");
s.sendRequest(request);
HTTPResponse response;
@ -73,7 +73,7 @@ void HTTPClientSessionTest::testGetLarge()
void HTTPClientSessionTest::testHead()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_HEAD, "/large");
s.sendRequest(request);
HTTPResponse response;
@ -88,7 +88,7 @@ void HTTPClientSessionTest::testHead()
void HTTPClientSessionTest::testPostSmallIdentity()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/echo");
std::string body("this is a random request body\r\n0\r\n");
request.setContentLength((int) body.length());
@ -105,7 +105,7 @@ void HTTPClientSessionTest::testPostSmallIdentity()
void HTTPClientSessionTest::testPostLargeIdentity()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/echo");
std::string body(8000, 'x');
body.append("\r\n0\r\n");
@ -123,7 +123,7 @@ void HTTPClientSessionTest::testPostLargeIdentity()
void HTTPClientSessionTest::testPostSmallChunked()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/echo");
std::string body("this is a random request body");
request.setChunkedTransferEncoding(true);
@ -141,7 +141,7 @@ void HTTPClientSessionTest::testPostSmallChunked()
void HTTPClientSessionTest::testPostLargeChunked()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/echo");
std::string body(16000, 'x');
request.setChunkedTransferEncoding(true);
@ -161,7 +161,7 @@ void HTTPClientSessionTest::testPostLargeChunked()
void HTTPClientSessionTest::testPostSmallClose()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/echo");
std::string body("this is a random request body");
s.sendRequest(request) << body;
@ -178,7 +178,7 @@ void HTTPClientSessionTest::testPostSmallClose()
void HTTPClientSessionTest::testPostLargeClose()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/echo");
std::string body(8000, 'x');
s.sendRequest(request) << body;
@ -195,7 +195,7 @@ void HTTPClientSessionTest::testPostLargeClose()
void HTTPClientSessionTest::testKeepAlive()
{
HTTPTestServer srv;
HTTPClientSession s("localhost", srv.port());
HTTPClientSession s("127.0.0.1", srv.port());
s.setKeepAlive(true);
HTTPRequest request(HTTPRequest::HTTP_HEAD, "/keepAlive", HTTPMessage::HTTP_1_1);
s.sendRequest(request);
@ -244,7 +244,7 @@ void HTTPClientSessionTest::testProxy()
{
HTTPTestServer srv;
HTTPClientSession s("www.somehost.com");
s.setProxy("localhost", srv.port());
s.setProxy("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/large");
s.sendRequest(request);
HTTPResponse response;
@ -261,7 +261,7 @@ void HTTPClientSessionTest::testProxyAuth()
{
HTTPTestServer srv;
HTTPClientSession s("www.somehost.com");
s.setProxy("localhost", srv.port());
s.setProxy("127.0.0.1", srv.port());
s.setProxyCredentials("user", "pass");
HTTPRequest request(HTTPRequest::HTTP_GET, "/large");
s.sendRequest(request);
@ -284,7 +284,7 @@ void HTTPClientSessionTest::testBypassProxy()
proxyConfig.port = 80;
proxyConfig.nonProxyHosts = "localhost|127\\.0\\.0\\.1";
HTTPClientSession s1("localhost", 80);
HTTPClientSession s1("127.0.0.1", 80);
s1.setProxyConfig(proxyConfig);
assert (s1.bypassProxy());
@ -298,6 +298,47 @@ void HTTPClientSessionTest::testBypassProxy()
}
void HTTPClientSessionTest::testExpectContinue()
{
HTTPTestServer srv;
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/expect");
std::string body("this is a random request body\r\n0\r\n");
request.setContentLength((int) body.length());
request.setExpectContinue(true);
s.sendRequest(request) << body;
HTTPResponse response;
assert (s.peekResponse(response));
assert (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
std::istream& rs = s.receiveResponse(response);
assert (response.getStatus() == HTTPResponse::HTTP_OK);
assert (response.getContentLength() == body.length());
std::ostringstream ostr;
StreamCopier::copyStream(rs, ostr);
assert (ostr.str() == body);
}
void HTTPClientSessionTest::testExpectContinueFail()
{
HTTPTestServer srv;
HTTPClientSession s("127.0.0.1", srv.port());
HTTPRequest request(HTTPRequest::HTTP_POST, "/fail");
std::string body("this is a random request body\r\n0\r\n");
request.setContentLength((int) body.length());
request.setExpectContinue(true);
s.sendRequest(request) << body;
HTTPResponse response;
assert (!s.peekResponse(response));
assert (response.getStatus() == HTTPResponse::HTTP_BAD_REQUEST);
std::istream& rs = s.receiveResponse(response);
assert (response.getStatus() == HTTPResponse::HTTP_BAD_REQUEST);
std::ostringstream ostr;
StreamCopier::copyStream(rs, ostr);
assert (ostr.str().empty());
}
void HTTPClientSessionTest::setUp()
{
}
@ -325,6 +366,8 @@ CppUnit::Test* HTTPClientSessionTest::suite()
CppUnit_addTest(pSuite, HTTPClientSessionTest, testProxy);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testProxyAuth);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testBypassProxy);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testExpectContinue);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testExpectContinueFail);
return pSuite;
}

View File

@ -37,6 +37,8 @@ public:
void testProxy();
void testProxyAuth();
void testBypassProxy();
void testExpectContinue();
void testExpectContinueFail();
void setUp();
void tearDown();

View File

@ -196,8 +196,8 @@ void HTTPResponseTest::testCookies()
cookies.clear();
response2.getCookies(cookies);
assert (cookies.size() == 2);
assert (((cookies[0].getName() == "name1") && (cookies[1].getName() == "name2")) ||
((cookies[0].getName() == "name2") && (cookies[1].getName() == "name1")));
assert (cookies[0].getName() == "name1" && cookies[1].getName() == "name2"
|| cookies[0].getName() == "name2" && cookies[1].getName() == "name1");
}

View File

@ -144,7 +144,7 @@ void HTTPServerTest::testIdentityRequest()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody");
request.setContentLength((int) body.length());
@ -167,7 +167,7 @@ void HTTPServerTest::testPutIdentityRequest()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
std::string body(5000, 'x');
HTTPRequest request("PUT", "/echoBody");
request.setContentLength((int) body.length());
@ -190,7 +190,7 @@ void HTTPServerTest::testChunkedRequest()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody");
request.setContentType("text/plain");
@ -214,7 +214,7 @@ void HTTPServerTest::testClosedRequest()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody");
request.setContentType("text/plain");
@ -234,7 +234,7 @@ void HTTPServerTest::testIdentityRequestKeepAlive()
HTTPServer srv(new RequestHandlerFactory, 8008);
srv.start();
HTTPClientSession cs("localhost", srv.socket().address().port());
HTTPClientSession cs("127.0.0.1", srv.socket().address().port());
cs.setKeepAlive(true);
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1);
@ -265,7 +265,7 @@ void HTTPServerTest::testChunkedRequestKeepAlive()
HTTPServer srv(new RequestHandlerFactory, 8009);
srv.start();
HTTPClientSession cs("localhost", srv.socket().address().port());
HTTPClientSession cs("127.0.0.1", srv.socket().address().port());
cs.setKeepAlive(true);
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1);
@ -297,7 +297,7 @@ void HTTPServerTest::testClosedRequestKeepAlive()
HTTPServer srv(new RequestHandlerFactory, 8010);
srv.start();
HTTPClientSession cs("localhost", srv.socket().address().port());
HTTPClientSession cs("127.0.0.1", srv.socket().address().port());
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody");
request.setContentType("text/plain");
@ -322,7 +322,7 @@ void HTTPServerTest::testMaxKeepAlive()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
cs.setKeepAlive(true);
HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1);
request.setContentType("text/plain");
@ -378,7 +378,7 @@ void HTTPServerTest::testKeepAliveTimeout()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
cs.setKeepAlive(true);
cs.setKeepAliveTimeout(Poco::Timespan(2, 0));
HTTPRequest request("POST", "/echoBody", HTTPMessage::HTTP_1_1);
@ -422,7 +422,7 @@ void HTTPServerTest::test100Continue()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
std::string body(5000, 'x');
HTTPRequest request("POST", "/echoBody");
request.setContentLength((int) body.length());
@ -446,7 +446,7 @@ void HTTPServerTest::testRedirect()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
HTTPRequest request("GET", "/redirect");
cs.sendRequest(request);
HTTPResponse response;
@ -466,7 +466,7 @@ void HTTPServerTest::testAuth()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
HTTPRequest request("GET", "/auth");
cs.sendRequest(request);
HTTPResponse response;
@ -486,7 +486,7 @@ void HTTPServerTest::testNotImpl()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
HTTPRequest request("GET", "/notImpl");
cs.sendRequest(request);
HTTPResponse response;
@ -505,7 +505,7 @@ void HTTPServerTest::testBuffer()
HTTPServer srv(new RequestHandlerFactory, svs, pParams);
srv.start();
HTTPClientSession cs("localhost", svs.address().port());
HTTPClientSession cs("127.0.0.1", svs.address().port());
HTTPRequest request("GET", "/buffer");
cs.sendRequest(request);
HTTPResponse response;

View File

@ -42,7 +42,7 @@ void HTTPStreamFactoryTest::testNoRedirect()
{
HTTPTestServer server;
HTTPStreamFactory factory;
URI uri("http://localhost/large");
URI uri("http://127.0.0.1/large");
uri.setPort(server.port());
#ifndef POCO_ENABLE_CPP11
std::auto_ptr<std::istream> pStr(factory.open(uri));
@ -59,7 +59,7 @@ void HTTPStreamFactoryTest::testEmptyPath()
{
HTTPTestServer server;
HTTPStreamFactory factory;
URI uri("http://localhost");
URI uri("http://127.0.0.1");
uri.setPort(server.port());
#ifndef POCO_ENABLE_CPP11
std::auto_ptr<std::istream> pStr(factory.open(uri));
@ -77,7 +77,7 @@ void HTTPStreamFactoryTest::testRedirect()
HTTPTestServer server;
Poco::URIStreamOpener opener;
opener.registerStreamFactory("http", new HTTPStreamFactory);
URI uri("http://localhost/redirect");
URI uri("http://127.0.0.1/redirect");
uri.setPort(server.port());
#ifndef POCO_ENABLE_CPP11
std::auto_ptr<std::istream> pStr(opener.open(uri));
@ -93,7 +93,7 @@ void HTTPStreamFactoryTest::testRedirect()
void HTTPStreamFactoryTest::testProxy()
{
HTTPTestServer server;
HTTPStreamFactory factory("localhost", server.port());
HTTPStreamFactory factory("127.0.0.1", server.port());
URI uri("http://www.somehost.com/large");
#ifndef POCO_ENABLE_CPP11
std::auto_ptr<std::istream> pStr(factory.open(uri));
@ -110,7 +110,7 @@ void HTTPStreamFactoryTest::testError()
{
HTTPTestServer server;
HTTPStreamFactory factory;
URI uri("http://localhost/notfound");
URI uri("http://127.0.0.1/notfound");
uri.setPort(server.port());
try
{

View File

@ -140,6 +140,37 @@ std::string HTTPTestServer::handleRequest() const
if (_lastRequest.substr(0, 3) == "GET")
response.append(body);
}
else if (_lastRequest.substr(0, 12) == "POST /expect")
{
std::string::size_type pos = _lastRequest.find("\r\n\r\n");
pos += 4;
std::string body = _lastRequest.substr(pos);
response.append("HTTP/1.1 100 Continue\r\n\r\n");
response.append("HTTP/1.1 200 OK\r\n");
response.append("Content-Type: text/plain\r\n");
if (_lastRequest.find("Content-Length") != std::string::npos)
{
response.append("Content-Length: ");
response.append(NumberFormatter::format((int) body.size()));
response.append("\r\n");
}
else if (_lastRequest.find("chunked") != std::string::npos)
{
response.append("Transfer-Encoding: chunked\r\n");
}
response.append("Connection: Close\r\n");
response.append("\r\n");
response.append(body);
}
else if (_lastRequest.substr(0, 10) == "POST /fail")
{
std::string::size_type pos = _lastRequest.find("\r\n\r\n");
pos += 4;
std::string body = _lastRequest.substr(pos);
response.append("HTTP/1.1 400 Bad Request\r\n");
response.append("Connection: Close\r\n");
response.append("\r\n");
}
else if (_lastRequest.substr(0, 4) == "POST")
{
std::string::size_type pos = _lastRequest.find("\r\n\r\n");

View File

@ -46,9 +46,9 @@ ICMPClientTest::~ICMPClientTest()
void ICMPClientTest::testPing()
{
assert(ICMPClient::pingIPv4("localhost") > 0);
assert(ICMPClient::pingIPv4("127.0.0.1") > 0);
assert(_icmpClient.ping("localhost") > 0);
assert(_icmpClient.ping("127.0.0.1") > 0);
assert(_icmpClient.ping("www.appinf.com", 4) > 0);
// warning: may fail depending on the existence of the addresses at test site

View File

@ -429,6 +429,42 @@ void MailMessageTest::testReadMultiPart()
}
void MailMessageTest::testReadMultiPartWithAttachmentNames()
{
std::istringstream istr(
"Content-Type: multipart/mixed; boundary=MIME_boundary_01234567\r\n"
"Date: Thu, 1 Jan 1970 00:00:00 GMT\r\n"
"From: poco@appinf.com\r\n"
"Mime-Version: 1.0\r\n"
"Subject: Test Message\r\n"
"To: John Doe <john.doe@no.where>\r\n"
"\r\n"
"\r\n"
"--MIME_boundary_01234567\r\n"
"Content-Disposition: inline\r\n"
"Content-Transfer-Encoding: 8bit\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"Hello World!\r\n"
"\r\n"
"--MIME_boundary_01234567\r\n"
"Content-Disposition: attachment; filename=sample.dat\r\n"
"Content-Transfer-Encoding: base64\r\n"
"Content-Type: application/octet-stream; name=sample\r\n"
"\r\n"
"VGhpcyBpcyBzb21lIGJpbmFyeSBkYXRhLiBSZWFsbHku\r\n"
"--MIME_boundary_01234567--\r\n"
);
MailMessage message;
message.read(istr);
assert (message.parts().size() == 2);
assert (message.parts()[1].name == "sample");
assert (message.parts()[1].pSource->filename() == "sample.dat");
}
void MailMessageTest::testReadMultiPartDefaultTransferEncoding()
{
std::istringstream istr(

View File

@ -35,6 +35,7 @@ public:
void testReadQP();
void testRead8Bit();
void testReadMultiPart();
void testReadMultiPartWithAttachmentNames();
void testReadMultiPartDefaultTransferEncoding();
void testEncodeWord();

View File

@ -360,6 +360,23 @@ void MessageHeaderTest::testFieldLimit()
}
void MessageHeaderTest::testDecodeWord()
{
std::string coded("this is pure ASCII");
std::string decoded = MessageHeader::decodeWord(coded, "ISO-8859-1");
assert(decoded == coded);
coded = "(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)";
decoded = MessageHeader::decodeWord(coded, "ISO-8859-1");
assert(decoded == "(a b)");
coded = "Hello =?UTF-8?B?RnJhbmNpcw==?=, good bye";
decoded = MessageHeader::decodeWord(coded, "ISO-8859-1");
assert(decoded == "Hello Francis, good bye");
}
void MessageHeaderTest::setUp()
{
}
@ -390,6 +407,7 @@ CppUnit::Test* MessageHeaderTest::suite()
CppUnit_addTest(pSuite, MessageHeaderTest, testSplitElements);
CppUnit_addTest(pSuite, MessageHeaderTest, testSplitParameters);
CppUnit_addTest(pSuite, MessageHeaderTest, testFieldLimit);
CppUnit_addTest(pSuite, MessageHeaderTest, testDecodeWord);
return pSuite;
}

View File

@ -40,6 +40,7 @@ public:
void testSplitElements();
void testSplitParameters();
void testFieldLimit();
void testDecodeWord();
void setUp();
void tearDown();

View File

@ -48,7 +48,7 @@ MulticastSocketTest::~MulticastSocketTest()
void MulticastSocketTest::testMulticast()
{
MulticastEchoServer echoServer;
MulticastSocket ms;
MulticastSocket ms(SocketAddress::IPv4);
int n = ms.sendTo("hello", 5, echoServer.group());
assert (n == 5);
char buffer[256];

View File

@ -63,11 +63,11 @@ void NetworkInterfaceTest::testMap()
std::cout << std::endl << "----------" << std::endl;
std::cout << "Address " << counter << std::endl;
std::cout << "----------" << std::endl;
std::cout << "Address: " << ipIt->get<NetworkInterface::IP_ADDRESS>().toString() << std::endl;
std::cout << "Address: " << ipIt->get<NetworkInterface::IP_ADDRESS>() << std::endl;
IPAddress addr = ipIt->get<NetworkInterface::SUBNET_MASK>();
if (!addr.isWildcard()) std::cout << "Subnet: " << addr.toString() << " (/" << addr.prefixLength() << ")" << std::endl;
if (!addr.isWildcard()) std::cout << "Subnet: " << addr << " (/" << addr.prefixLength() << ")" << std::endl;
addr = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>();
if (!addr.isWildcard()) std::cout << "Broadcast: " << addr.toString() << std::endl;
if (!addr.isWildcard()) std::cout << "Broadcast: " << addr << std::endl;
}
std::cout << "=============" << std::endl << std::endl;
@ -98,11 +98,11 @@ void NetworkInterfaceTest::testList()
List::const_iterator ipEnd = ipList.end();
for (int counter = 0; ipIt != ipEnd; ++ipIt, ++counter)
{
std::cout << "IP Address: " << ipIt->get<NetworkInterface::IP_ADDRESS>().toString() << std::endl;
std::cout << "IP Address: " << ipIt->get<NetworkInterface::IP_ADDRESS>() << std::endl;
IPAddress addr = ipIt->get<NetworkInterface::SUBNET_MASK>();
if (!addr.isWildcard()) std::cout << "Subnet: " << ipIt->get<NetworkInterface::SUBNET_MASK>().toString() << " (/" << ipIt->get<NetworkInterface::SUBNET_MASK>().prefixLength() << ")" << std::endl;
if (!addr.isWildcard()) std::cout << "Subnet: " << ipIt->get<NetworkInterface::SUBNET_MASK>() << " (/" << ipIt->get<NetworkInterface::SUBNET_MASK>().prefixLength() << ")" << std::endl;
addr = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>();
if (!addr.isWildcard()) std::cout << "Broadcast: " << ipIt->get<NetworkInterface::BROADCAST_ADDRESS>().toString() << std::endl;
if (!addr.isWildcard()) std::cout << "Broadcast: " << ipIt->get<NetworkInterface::BROADCAST_ADDRESS>() << std::endl;
}
std::cout << "==============" << std::endl << std::endl;
@ -178,7 +178,7 @@ void NetworkInterfaceTest::testMapIpOnly()
{
assert(it->second.supportsIPv4() || it->second.supportsIPv6());
std::cout << "Interface: (" << it->second.index() << ")" << std::endl;
std::cout << "Address: " << it->second.address().toString() << std::endl;
std::cout << "Address: " << it->second.address() << std::endl;
NetworkInterface::MACAddress mac(it->second.macAddress());
if (!mac.empty() && (it->second.type() != NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK))
std::cout << "MAC Address:" << mac << std::endl;

View File

@ -40,7 +40,7 @@ void POP3ClientSessionTest::testLogin()
server.addResponse("+OK USER");
server.addResponse("+OK PASS");
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
std::string cmd = server.popCommand();
assert (cmd == "USER user");
@ -59,7 +59,7 @@ void POP3ClientSessionTest::testLoginFail()
server.addResponse("+OK USER");
server.addResponse("-ERR PASS");
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
try
{
session.login("user", "secret");
@ -80,7 +80,7 @@ void POP3ClientSessionTest::testMessageCount()
server.addResponse("+OK PASS");
server.addResponse("+OK 42 12345");
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
server.clearCommands();
int n = session.messageCount();
@ -105,7 +105,7 @@ void POP3ClientSessionTest::testList()
".\r\n"
);
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
server.clearCommands();
std::vector<POP3ClientSession::MessageInfo> infos;
@ -144,7 +144,7 @@ void POP3ClientSessionTest::testRetrieveMessage()
".\r\n"
);
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
server.clearCommands();
MailMessage message;
@ -180,7 +180,7 @@ void POP3ClientSessionTest::testRetrieveHeader()
"."
);
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
server.clearCommands();
MessageHeader header;
@ -223,7 +223,7 @@ void POP3ClientSessionTest::testRetrieveMessages()
"."
);
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
server.clearCommands();
MessageHeader header;
@ -259,7 +259,7 @@ void POP3ClientSessionTest::testDeleteMessage()
server.addResponse("+OK PASS");
server.addResponse("+OK DELETED");
server.addResponse("+OK QUIT");
POP3ClientSession session("localhost", server.port());
POP3ClientSession session("127.0.0.1", server.port());
session.login("user", "secret");
server.clearCommands();
session.deleteMessage(42);

View File

@ -43,7 +43,7 @@ RawSocketTest::~RawSocketTest()
void RawSocketTest::testEchoIPv4()
{
SocketAddress sa("localhost", 0);
SocketAddress sa("127.0.0.1", 0);
RawSocket rs(IPAddress::IPv4);
rs.connect(sa);
@ -68,7 +68,7 @@ void RawSocketTest::testSendToReceiveFromIPv4()
{
RawSocket rs(IPAddress::IPv4);
int n = rs.sendTo("hello", 5, SocketAddress("localhost", 0));
int n = rs.sendTo("hello", 5, SocketAddress("127.0.0.1", 0));
assert (n == 5);
char buffer[256] = "";

View File

@ -40,7 +40,7 @@ void SMTPClientSessionTest::testLoginEHLO()
server.addResponse("220 localhost SMTP ready");
server.addResponse("250 Hello localhost");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
session.login("localhost");
std::string cmd = server.popCommand();
assert (cmd == "EHLO localhost");
@ -57,7 +57,7 @@ void SMTPClientSessionTest::testLoginHELO()
server.addResponse("500 EHLO not understood");
server.addResponse("250 Hello localhost");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
session.login("localhost");
std::string cmd = server.popCommand();
assert (cmd == "EHLO localhost");
@ -74,7 +74,7 @@ void SMTPClientSessionTest::testLoginFailed()
DialogServer server;
server.addResponse("500 No SMTP service here");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
try
{
session.login("localhost");
@ -97,7 +97,7 @@ void SMTPClientSessionTest::testSend()
server.addResponse("354 Send data");
server.addResponse("250 OK");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
session.login("localhost");
MailMessage message;
@ -151,7 +151,7 @@ void SMTPClientSessionTest::testSendMultiRecipient()
server.addResponse("250 OK");
server.addResponse("250 OK");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
session.login("localhost");
MailMessage message;
@ -216,7 +216,7 @@ void SMTPClientSessionTest::testMultiSeparateRecipient()
server.addResponse("250 OK");
server.addResponse("250 OK");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
session.login("localhost");
MailMessage message;
@ -283,7 +283,7 @@ void SMTPClientSessionTest::testSendFailed()
server.addResponse("354 Send data");
server.addResponse("500 Error");
server.addResponse("221 Bye");
SMTPClientSession session("localhost", server.port());
SMTPClientSession session("127.0.0.1", server.port());
session.login("localhost");
MailMessage message;

View File

@ -21,6 +21,7 @@ using Poco::Net::InvalidAddressException;
using Poco::Net::HostNotFoundException;
using Poco::Net::ServiceNotFoundException;
using Poco::Net::NoAddressFoundException;
using Poco::Net::AddressFamilyMismatchException;
using Poco::InvalidArgumentException;
@ -41,8 +42,11 @@ void SocketAddressTest::testSocketAddress()
assert (wild.port() == 0);
SocketAddress sa1("192.168.1.100", 100);
assert (sa1.af() == AF_INET);
assert (sa1.family() == SocketAddress::IPv4);
assert (sa1.host().toString() == "192.168.1.100");
assert (sa1.port() == 100);
assert (sa1.toString() == "192.168.1.100:100");
SocketAddress sa2("192.168.1.100", "100");
assert (sa2.host().toString() == "192.168.1.100");
@ -63,7 +67,7 @@ void SocketAddressTest::testSocketAddress()
{
}
SocketAddress sa4("www.appinf.com", 80);
SocketAddress sa4("pocoproject.org", 80);
assert (sa4.host().toString() == "162.209.7.4");
assert (sa4.port() == 80);
@ -113,6 +117,24 @@ void SocketAddressTest::testSocketAddress()
catch (InvalidArgumentException&)
{
}
SocketAddress sa10("www6.pocoproject.org", 80);
assert (sa10.host().toString() == "162.209.7.4" || sa10.host().toString() == "[2001:4801:7819:74:be76:4eff:fe10:6b73]");
SocketAddress sa11(SocketAddress::IPv4, "www6.pocoproject.org", 80);
assert (sa11.host().toString() == "162.209.7.4");
#ifdef POCO_HAVE_IPv6
try
{
SocketAddress sa12(SocketAddress::IPv6, "www6.pocoproject.org", 80);
assert (sa12.host().toString() == "2001:4801:7819:74:be76:4eff:fe10:6b73");
}
catch (AddressFamilyMismatchException&)
{
// may happen if no IPv6 address is configured on the system
}
#endif
}
@ -133,6 +155,42 @@ void SocketAddressTest::testSocketRelationals()
void SocketAddressTest::testSocketAddress6()
{
#ifdef POCO_HAVE_IPv6
SocketAddress sa1("FE80::E6CE:8FFF:FE4A:EDD0", 100);
assert (sa1.af() == AF_INET6);
assert (sa1.family() == SocketAddress::IPv6);
assert (sa1.host().toString() == "fe80::e6ce:8fff:fe4a:edd0");
assert (sa1.port() == 100);
assert (sa1.toString() == "[fe80::e6ce:8fff:fe4a:edd0]:100");
SocketAddress sa2("[FE80::E6CE:8FFF:FE4A:EDD0]:100");
assert (sa2.af() == AF_INET6);
assert (sa2.family() == SocketAddress::IPv6);
assert (sa2.host().toString() == "fe80::e6ce:8fff:fe4a:edd0");
assert (sa2.port() == 100);
assert (sa2.toString() == "[fe80::e6ce:8fff:fe4a:edd0]:100");
#endif
}
void SocketAddressTest::testSocketAddressUnixLocal()
{
#ifdef POCO_OS_FAMILY_UNIX
SocketAddress sa1(SocketAddress::UNIX_LOCAL, "/tmp/sock1");
assert (sa1.af() == AF_UNIX);
assert (sa1.family() == SocketAddress::UNIX_LOCAL);
assert (sa1.toString() == "/tmp/sock1");
SocketAddress sa2(SocketAddress::UNIX_LOCAL, "/tmp/sock2");
assert (sa1 != sa2);
assert (sa1 < sa2);
SocketAddress sa3(SocketAddress::UNIX_LOCAL, "/tmp/sock1");
assert (sa1 == sa3);
assert (!(sa1 < sa3));
SocketAddress sa4("/tmp/sock1");
assert (sa1 == sa4);
assert (sa4.toString() == "/tmp/sock1");
#endif
}
@ -154,6 +212,7 @@ CppUnit::Test* SocketAddressTest::suite()
CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddress);
CppUnit_addTest(pSuite, SocketAddressTest, testSocketRelationals);
CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddress6);
CppUnit_addTest(pSuite, SocketAddressTest, testSocketAddressUnixLocal);
return pSuite;
}

View File

@ -27,6 +27,7 @@ public:
void testSocketAddress();
void testSocketRelationals();
void testSocketAddress6();
void testSocketAddressUnixLocal();
void setUp();
void tearDown();

View File

@ -312,7 +312,7 @@ void SocketReactorTest::testSocketReactor()
ServerSocket ss(ssa);
SocketReactor reactor;
SocketAcceptor<EchoServiceHandler> acceptor(ss, reactor);
SocketAddress sa("localhost", ss.address().port());
SocketAddress sa("127.0.0.1", ss.address().port());
SocketConnector<ClientServiceHandler> connector(sa, reactor);
ClientServiceHandler::setOnce(true);
ClientServiceHandler::resetData();
@ -332,7 +332,7 @@ void SocketReactorTest::testSetSocketReactor()
SocketReactor reactor;
SocketAcceptor<EchoServiceHandler> acceptor(ss);
acceptor.setReactor(reactor);
SocketAddress sa("localhost", ss.address().port());
SocketAddress sa("127.0.0.1", ss.address().port());
SocketConnector<ClientServiceHandler> connector(sa, reactor);
ClientServiceHandler::setOnce(true);
ClientServiceHandler::resetData();
@ -351,7 +351,7 @@ void SocketReactorTest::testParallelSocketReactor()
ServerSocket ss(ssa);
SocketReactor reactor;
ParallelSocketAcceptor<EchoServiceHandler, SocketReactor> acceptor(ss, reactor);
SocketAddress sa("localhost", ss.address().port());
SocketAddress sa("127.0.0.1", ss.address().port());
SocketConnector<ClientServiceHandler> connector1(sa, reactor);
SocketConnector<ClientServiceHandler> connector2(sa, reactor);
SocketConnector<ClientServiceHandler> connector3(sa, reactor);
@ -388,7 +388,7 @@ void SocketReactorTest::testSocketConnectorTimeout()
SocketAddress ssa;
ServerSocket ss(ssa);
SocketReactor reactor;
SocketAddress sa("localhost", ss.address().port());
SocketAddress sa("127.0.0.1", ss.address().port());
SocketConnector<ClientServiceHandler> connector(sa, reactor);
reactor.run();
assert (ClientServiceHandler::timeout());

View File

@ -47,7 +47,7 @@ void SocketStreamTest::testStreamEcho()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
SocketStream str(ss);
str << "hello";
assert (str.good());
@ -70,7 +70,7 @@ void SocketStreamTest::testLargeStreamEcho()
const int msgSize = 64000;
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
SocketStream str(ss);
ss.setSendBufferSize(msgSize);
ss.setReceiveBufferSize(msgSize);
@ -98,7 +98,7 @@ void SocketStreamTest::testEOF()
{
EchoServer echoServer;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
str << "hello";
assert (str.good());
str.flush();

View File

@ -21,6 +21,7 @@
#include "Poco/Buffer.h"
#include "Poco/FIFOBuffer.h"
#include "Poco/Delegate.h"
#include "Poco/File.h"
#include <iostream>
@ -52,7 +53,7 @@ void SocketTest::testEcho()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
int n = ss.sendBytes("hello", 5);
assert (n == 5);
char buffer[256];
@ -67,7 +68,7 @@ void SocketTest::testPoll()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
Stopwatch sw;
sw.start();
Timespan timeout(1000000);
@ -92,7 +93,7 @@ void SocketTest::testAvailable()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
Timespan timeout(1000000);
ss.sendBytes("hello", 5);
char buffer[256];
@ -132,7 +133,7 @@ void SocketTest::testFIFOBuffer()
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
int n = ss.sendBytes(f);
assert (n == 5);
assert(1 == _notToReadable);
@ -169,7 +170,7 @@ void SocketTest::testConnect()
serv.listen();
StreamSocket ss;
Timespan timeout(250000);
ss.connect(SocketAddress("localhost", serv.address().port()), timeout);
ss.connect(SocketAddress("127.0.0.1", serv.address().port()), timeout);
}
@ -184,7 +185,7 @@ void SocketTest::testConnectRefused()
Timespan timeout(250000);
try
{
ss.connect(SocketAddress("localhost", port));
ss.connect(SocketAddress("127.0.0.1", port));
fail("connection refused - must throw");
}
catch (ConnectionRefusedException&)
@ -204,7 +205,7 @@ void SocketTest::testConnectRefusedNB()
Timespan timeout(2, 0);
try
{
ss.connect(SocketAddress("localhost", port), timeout);
ss.connect(SocketAddress("127.0.0.1", port), timeout);
fail("connection refused - must throw");
}
catch (TimeoutException&)
@ -220,7 +221,7 @@ void SocketTest::testNonBlocking()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
ss.setBlocking(false);
Timespan timeout(1000000);
@ -244,7 +245,7 @@ void SocketTest::testAddress()
serv.bind(SocketAddress());
serv.listen();
StreamSocket ss;
ss.connect(SocketAddress("localhost", serv.address().port()));
ss.connect(SocketAddress("127.0.0.1", serv.address().port()));
StreamSocket css = serv.acceptConnection();
assert (css.peerAddress().host() == ss.address().host());
assert (css.peerAddress().port() == ss.address().port());
@ -306,7 +307,7 @@ void SocketTest::testTimeout()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
Timespan timeout0 = ss.getReceiveTimeout();
Timespan timeout(250000);
@ -344,7 +345,7 @@ void SocketTest::testTimeout()
void SocketTest::testBufferSize()
{
EchoServer echoServer;
SocketAddress sa("localhost", 1234);
SocketAddress sa("127.0.0.1", 1234);
StreamSocket ss(sa.family());
int osz = ss.getSendBufferSize();
@ -368,7 +369,7 @@ void SocketTest::testOptions()
{
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
ss.setLinger(true, 20);
bool f;
@ -402,7 +403,7 @@ void SocketTest::testSelect()
EchoServer echoServer;
StreamSocket ss;
ss.connect(SocketAddress("localhost", echoServer.port()));
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
Socket::SocketList readList;
Socket::SocketList writeList;
@ -439,8 +440,8 @@ void SocketTest::testSelect2()
EchoServer echoServer1;
EchoServer echoServer2;
StreamSocket ss1(SocketAddress("localhost", echoServer1.port()));
StreamSocket ss2(SocketAddress("localhost", echoServer2.port()));
StreamSocket ss1(SocketAddress("127.0.0.1", echoServer1.port()));
StreamSocket ss2(SocketAddress("127.0.0.1", echoServer2.port()));
Socket::SocketList readList;
Socket::SocketList writeList;
@ -499,6 +500,28 @@ void SocketTest::testSelect3()
}
void SocketTest::testEchoUnixLocal()
{
#if defined(POCO_OS_FAMILY_UNIX)
Poco::File socketFile("/tmp/SocketTest.sock");
if (socketFile.exists()) socketFile.remove();
SocketAddress localAddr(SocketAddress::UNIX_LOCAL, socketFile.path());
EchoServer echoServer(localAddr);
StreamSocket ss(SocketAddress::UNIX_LOCAL);
ss.connect(localAddr);
int n = ss.sendBytes("hello", 5);
assert (n == 5);
char buffer[256];
n = ss.receiveBytes(buffer, sizeof(buffer));
assert (n == 5);
assert (std::string(buffer, n) == "hello");
ss.close();
socketFile.remove();
#endif
}
void SocketTest::onReadable(bool& b)
{
if (b) ++_notToReadable;
@ -547,6 +570,7 @@ CppUnit::Test* SocketTest::suite()
CppUnit_addTest(pSuite, SocketTest, testSelect);
CppUnit_addTest(pSuite, SocketTest, testSelect2);
CppUnit_addTest(pSuite, SocketTest, testSelect3);
CppUnit_addTest(pSuite, SocketTest, testEchoUnixLocal);
return pSuite;
}

View File

@ -40,6 +40,7 @@ public:
void testSelect();
void testSelect2();
void testSelect3();
void testEchoUnixLocal();
void setUp();
void tearDown();

View File

@ -123,7 +123,7 @@ SyslogTest::~SyslogTest()
void SyslogTest::testListener()
{
Poco::AutoPtr<RemoteSyslogChannel> channel = new RemoteSyslogChannel();
channel->setProperty("loghost", "localhost:51400");
channel->setProperty("loghost", "127.0.0.1:51400");
channel->open();
Poco::AutoPtr<RemoteSyslogListener> listener = new RemoteSyslogListener(51400);
listener->open();
@ -148,7 +148,7 @@ void SyslogTest::testListener()
void SyslogTest::testChannelOpenClose()
{
Poco::AutoPtr<RemoteSyslogChannel> channel = new RemoteSyslogChannel();
channel->setProperty("loghost", "localhost:51400");
channel->setProperty("loghost", "127.0.0.1:51400");
channel->open();
Poco::AutoPtr<RemoteSyslogListener> listener = new RemoteSyslogListener(51400);
listener->open();
@ -187,7 +187,7 @@ void SyslogTest::testChannelOpenClose()
void SyslogTest::testOldBSD()
{
Poco::AutoPtr<RemoteSyslogChannel> channel = new RemoteSyslogChannel();
channel->setProperty("loghost", "localhost:51400");
channel->setProperty("loghost", "127.0.0.1:51400");
channel->setProperty("format", "bsd");
channel->open();
Poco::AutoPtr<RemoteSyslogListener> listener = new RemoteSyslogListener(51400);

View File

@ -22,6 +22,7 @@
using Poco::Net::TCPServer;
using Poco::Net::TCPServerConnectionFilter;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::TCPServerConnectionFactoryImpl;
@ -60,6 +61,15 @@ namespace
}
}
};
class RejectFilter: public TCPServerConnectionFilter
{
public:
bool accept(const StreamSocket&)
{
return false;
}
};
}
@ -82,7 +92,7 @@ void TCPServerTest::testOneConnection()
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 0);
SocketAddress sa("localhost", srv.socket().address().port());
SocketAddress sa("127.0.0.1", srv.socket().address().port());
StreamSocket ss1(sa);
std::string data("hello, world");
ss1.sendBytes(data.data(), (int) data.size());
@ -109,7 +119,7 @@ void TCPServerTest::testTwoConnections()
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 0);
SocketAddress sa("localhost", srv.socket().address().port());
SocketAddress sa("127.0.0.1", srv.socket().address().port());
StreamSocket ss1(sa);
StreamSocket ss2(sa);
std::string data("hello, world");
@ -157,7 +167,7 @@ void TCPServerTest::testMultiConnections()
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 0);
SocketAddress sa("localhost", svs.address().port());
SocketAddress sa("127.0.0.1", svs.address().port());
StreamSocket ss1(sa);
StreamSocket ss2(sa);
StreamSocket ss3(sa);
@ -231,7 +241,9 @@ void TCPServerTest::testMultiConnections()
assert (srv.currentConnections() == 0);
}
void TCPServerTest::testThreadCapacity(){
void TCPServerTest::testThreadCapacity()
{
ServerSocket svs(0);
TCPServerParams* pParams = new TCPServerParams;
pParams->setMaxThreads(64);
@ -241,6 +253,29 @@ void TCPServerTest::testThreadCapacity(){
}
void TCPServerTest::testFilter()
{
TCPServer srv(new TCPServerConnectionFactoryImpl<EchoConnection>());
srv.setConnectionFilter(new RejectFilter);
srv.start();
assert (srv.currentConnections() == 0);
assert (srv.currentThreads() == 0);
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 0);
SocketAddress sa("127.0.0.1", srv.socket().address().port());
StreamSocket ss(sa);
char buffer[256];
int n = ss.receiveBytes(buffer, sizeof(buffer));
assert (n == 0);
assert (srv.currentConnections() == 0);
assert (srv.currentThreads() == 0);
assert (srv.queuedConnections() == 0);
assert (srv.totalConnections() == 0);
}
void TCPServerTest::setUp()
{
@ -260,6 +295,7 @@ CppUnit::Test* TCPServerTest::suite()
CppUnit_addTest(pSuite, TCPServerTest, testTwoConnections);
CppUnit_addTest(pSuite, TCPServerTest, testMultiConnections);
CppUnit_addTest(pSuite, TCPServerTest, testThreadCapacity);
CppUnit_addTest(pSuite, TCPServerTest, testFilter);
return pSuite;
}

View File

@ -28,6 +28,7 @@ public:
void testTwoConnections();
void testMultiConnections();
void testThreadCapacity();
void testFilter();
void setUp();
void tearDown();

View File

@ -118,7 +118,7 @@ void WebSocketTest::testWebSocket()
Poco::Thread::sleep(200);
HTTPClientSession cs("localhost", ss.address().port());
HTTPClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
@ -140,6 +140,13 @@ void WebSocketTest::testWebSocket()
assert (n == payload.size());
assert (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assert (flags == WebSocket::FRAME_TEXT);
ws.sendFrame(payload.data(), (int) payload.size());
Poco::Buffer<char> pocobuffer(0);
n = ws.receiveFrame(pocobuffer, flags);
assert (n == payload.size());
assert (payload.compare(0, payload.size(), pocobuffer.begin(), 0, n) == 0);
assert (flags == WebSocket::FRAME_TEXT);
}
for (int i = 125; i < 129; i++)
@ -150,6 +157,13 @@ void WebSocketTest::testWebSocket()
assert (n == payload.size());
assert (payload.compare(0, payload.size(), buffer, 0, n) == 0);
assert (flags == WebSocket::FRAME_TEXT);
ws.sendFrame(payload.data(), (int) payload.size());
Poco::Buffer<char> pocobuffer(0);
n = ws.receiveFrame(pocobuffer, flags);
assert (n == payload.size());
assert (payload.compare(0, payload.size(), pocobuffer.begin(), 0, n) == 0);
assert (flags == WebSocket::FRAME_TEXT);
}
payload = "Hello, world!";
@ -185,7 +199,7 @@ void WebSocketTest::testWebSocketLarge()
Poco::Thread::sleep(200);
HTTPClientSession cs("localhost", ss.address().port());
HTTPClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
@ -209,6 +223,49 @@ void WebSocketTest::testWebSocketLarge()
}
void WebSocketTest::testOneLargeFrame(int msgSize)
{
Poco::Net::ServerSocket ss(0);
Poco::Net::HTTPServer server(new WebSocketRequestHandlerFactory(msgSize), ss, new Poco::Net::HTTPServerParams);
server.start();
Poco::Thread::sleep(200);
HTTPClientSession cs("127.0.0.1", ss.address().port());
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", HTTPRequest::HTTP_1_1);
HTTPResponse response;
WebSocket ws(cs, request, response);
ws.setSendBufferSize(msgSize);
ws.setReceiveBufferSize(msgSize);
std::string payload(msgSize, 'x');
ws.sendFrame(payload.data(), msgSize);
Poco::Buffer<char> buffer(msgSize);
int flags;
int n;
n = ws.receiveFrame(buffer.begin(), buffer.size(), flags);
assert (n == payload.size());
assert (payload.compare(0, payload.size(), buffer.begin(), 0, n) == 0);
ws.sendFrame(payload.data(), msgSize);
Poco::Buffer<char> pocobuffer(0);
n = ws.receiveFrame(pocobuffer, flags);
assert (n == payload.size());
assert (payload.compare(0, payload.size(), pocobuffer.begin(), 0, n) == 0);
}
void WebSocketTest::testWebSocketLargeInOneFrame()
{
testOneLargeFrame(64000);
testOneLargeFrame(70000);
}
void WebSocketTest::setUp()
{
}
@ -225,6 +282,7 @@ CppUnit::Test* WebSocketTest::suite()
CppUnit_addTest(pSuite, WebSocketTest, testWebSocket);
CppUnit_addTest(pSuite, WebSocketTest, testWebSocketLarge);
CppUnit_addTest(pSuite, WebSocketTest, testWebSocketLargeInOneFrame);
return pSuite;
}

View File

@ -26,6 +26,7 @@ public:
void testWebSocket();
void testWebSocketLarge();
void testWebSocketLargeInOneFrame();
void setUp();
void tearDown();
@ -33,6 +34,7 @@ public:
static CppUnit::Test* suite();
private:
void testOneLargeFrame(int msgSize);
};