mirror of
https://github.com/Telecominfraproject/wlan-cloud-lib-poco.git
synced 2026-01-07 21:01:47 +00:00
feat(HTTPClientSession): HTTPClientSession source IP address #2271
This commit is contained in:
@@ -116,6 +116,9 @@ public:
|
||||
HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig);
|
||||
/// Creates a HTTPClientSession using the given host, port and proxy configuration.
|
||||
|
||||
HTTPClientSession(const StreamSocket& socket, const ProxyConfig& proxyConfig);
|
||||
/// Creates a HTTPClientSession using the given socket and proxy configuration.
|
||||
|
||||
virtual ~HTTPClientSession();
|
||||
/// Destroys the HTTPClientSession and closes
|
||||
/// the underlying socket.
|
||||
@@ -138,6 +141,32 @@ public:
|
||||
Poco::UInt16 getPort() const;
|
||||
/// Returns the port number of the target HTTP server.
|
||||
|
||||
void setSourceAddress(const SocketAddress& address);
|
||||
/// Sets the source IP address and source port for the HTTPClientSession
|
||||
/// socket.
|
||||
///
|
||||
/// Function can be called repeatedly to set one source address value for
|
||||
/// IPv4 and one for IPv6, in the case where it is not known ahead of time
|
||||
/// which type of address family the target host is part of.
|
||||
///
|
||||
/// The source address must not be changed once there
|
||||
/// is an open connection to the server.
|
||||
///
|
||||
/// Note: Both the source IP address and source port can be set
|
||||
/// using this function, but the typical client use is to set
|
||||
/// the source IP address only and the source port portion
|
||||
/// would normally be passed as 0 meaning that any port value
|
||||
/// can be used on the source side of the socket.
|
||||
|
||||
const SocketAddress& getSourceAddress();
|
||||
/// Returns the last source address set with setSourceAddress
|
||||
|
||||
const SocketAddress& getSourceAddress4();
|
||||
/// Returns the last IPv4 source address set with setSourceAddress
|
||||
|
||||
const SocketAddress& getSourceAddress6();
|
||||
/// Returns the last IPV6 source address set with setSourceAddress
|
||||
|
||||
void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT);
|
||||
/// Sets the proxy host name and port number.
|
||||
|
||||
@@ -335,8 +364,14 @@ protected:
|
||||
/// to the HTTPClientSession.
|
||||
|
||||
private:
|
||||
using OStreamPtr = Poco::SharedPtr<std::ostream>;
|
||||
using IStreamPtr = Poco::SharedPtr<std::istream>;
|
||||
|
||||
std::string _host;
|
||||
Poco::UInt16 _port;
|
||||
SocketAddress _sourceAddress;
|
||||
SocketAddress _sourceAddress4;
|
||||
SocketAddress _sourceAddress6;
|
||||
ProxyConfig _proxyConfig;
|
||||
Poco::Timespan _keepAliveTimeout;
|
||||
Poco::Timestamp _lastRequest;
|
||||
@@ -344,8 +379,8 @@ private:
|
||||
bool _mustReconnect;
|
||||
bool _expectResponseBody;
|
||||
bool _responseReceived;
|
||||
Poco::SharedPtr<std::ostream> _pRequestStream;
|
||||
Poco::SharedPtr<std::istream> _pResponseStream;
|
||||
OStreamPtr _pRequestStream;
|
||||
IStreamPtr _pResponseStream;
|
||||
HTTPBasicCredentials _proxyBasicCreds;
|
||||
HTTPDigestCredentials _proxyDigestCreds;
|
||||
HTTPNTLMCredentials _proxyNTLMCreds;
|
||||
|
||||
@@ -165,6 +165,10 @@ protected:
|
||||
/// Connects the underlying socket to the given address
|
||||
/// and sets the socket's receive timeout.
|
||||
|
||||
void connect(const SocketAddress& targetAddress, const SocketAddress& sourceAddress);
|
||||
/// Binds the underlying socket to the source address
|
||||
/// and connects to the targetAddress.
|
||||
|
||||
void attachSocket(const StreamSocket& socket);
|
||||
/// Attaches a socket to the session, replacing the
|
||||
/// previously attached socket.
|
||||
|
||||
@@ -128,6 +128,27 @@ public:
|
||||
/// the TCP server at the given address. Prior to opening the
|
||||
/// connection the socket is set to nonblocking mode.
|
||||
|
||||
void bind(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
|
||||
/// Bind a local address to the socket.
|
||||
///
|
||||
/// This is usually only done when establishing a server
|
||||
/// socket.
|
||||
///
|
||||
/// TCP clients normally do not bind to a local address,
|
||||
/// but in some special advanced cases it may be useful to have
|
||||
/// this type of functionality. (e.g. in multihoming situations
|
||||
/// where the traffic will be sent through a particular interface;
|
||||
/// or in computer clustered environments with active/standby
|
||||
/// servers and it is desired to make the traffic from either
|
||||
/// active host present the same source IP address).
|
||||
///
|
||||
/// Note: Practical use of client source IP address binding
|
||||
/// may require OS networking setup outside the scope of
|
||||
/// the Poco library.
|
||||
///
|
||||
/// If reuseAddress is true, sets the SO_REUSEADDR
|
||||
/// socket option.
|
||||
|
||||
void shutdownReceive();
|
||||
/// Shuts down the receiving part of the socket connection.
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig;
|
||||
|
||||
HTTPClientSession::HTTPClientSession():
|
||||
_port(HTTPSession::HTTP_PORT),
|
||||
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
|
||||
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
|
||||
_proxyConfig(_globalProxyConfig),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
@@ -54,6 +56,8 @@ HTTPClientSession::HTTPClientSession():
|
||||
HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
|
||||
HTTPSession(socket),
|
||||
_port(HTTPSession::HTTP_PORT),
|
||||
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
|
||||
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
|
||||
_proxyConfig(_globalProxyConfig),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
@@ -68,6 +72,8 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
|
||||
HTTPClientSession::HTTPClientSession(const SocketAddress& address):
|
||||
_host(address.host().toString()),
|
||||
_port(address.port()),
|
||||
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
|
||||
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
|
||||
_proxyConfig(_globalProxyConfig),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
@@ -82,6 +88,8 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
|
||||
HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port):
|
||||
_host(host),
|
||||
_port(port),
|
||||
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
|
||||
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
|
||||
_proxyConfig(_globalProxyConfig),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
@@ -107,6 +115,21 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port,
|
||||
}
|
||||
|
||||
|
||||
HTTPClientSession::HTTPClientSession(const StreamSocket& socket, const ProxyConfig& proxyConfig):
|
||||
HTTPSession(socket),
|
||||
_port(HTTPSession::HTTP_PORT),
|
||||
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
|
||||
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
|
||||
_proxyConfig(proxyConfig),
|
||||
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
|
||||
_reconnect(false),
|
||||
_mustReconnect(false),
|
||||
_expectResponseBody(false),
|
||||
_responseReceived(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HTTPClientSession::~HTTPClientSession()
|
||||
{
|
||||
}
|
||||
@@ -130,6 +153,39 @@ void HTTPClientSession::setPort(Poco::UInt16 port)
|
||||
}
|
||||
|
||||
|
||||
void HTTPClientSession::setSourceAddress(const SocketAddress& address)
|
||||
{
|
||||
if (!connected())
|
||||
{
|
||||
if (address.family() == IPAddress::IPv4)
|
||||
_sourceAddress4 = address;
|
||||
else
|
||||
_sourceAddress6 = address;
|
||||
_sourceAddress = address;
|
||||
}
|
||||
else
|
||||
throw IllegalStateException("Cannot set the source address for an already connected session");
|
||||
}
|
||||
|
||||
|
||||
const SocketAddress& HTTPClientSession::getSourceAddress()
|
||||
{
|
||||
return _sourceAddress;
|
||||
}
|
||||
|
||||
|
||||
const SocketAddress& HTTPClientSession::getSourceAddress4()
|
||||
{
|
||||
return _sourceAddress4;
|
||||
}
|
||||
|
||||
|
||||
const SocketAddress& HTTPClientSession::getSourceAddress6()
|
||||
{
|
||||
return _sourceAddress6;
|
||||
}
|
||||
|
||||
|
||||
void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
|
||||
{
|
||||
if (!connected())
|
||||
@@ -400,16 +456,22 @@ int HTTPClientSession::write(const char* buffer, std::streamsize length)
|
||||
|
||||
void HTTPClientSession::reconnect()
|
||||
{
|
||||
if (_proxyConfig.host.empty() || bypassProxy())
|
||||
{
|
||||
SocketAddress addr(_host, _port);
|
||||
connect(addr);
|
||||
}
|
||||
if (_proxyConfig.host.empty() || bypassProxy())
|
||||
addr = SocketAddress(_host, _port);
|
||||
else
|
||||
addr = SocketAddress(_proxyConfig.host, _proxyConfig.port);
|
||||
|
||||
SocketAddress sourceAddr;
|
||||
if (addr.family() == IPAddress::IPv4)
|
||||
sourceAddr = _sourceAddress4;
|
||||
else
|
||||
sourceAddr = _sourceAddress6;
|
||||
|
||||
if ((!sourceAddr.host().isWildcard()) || (sourceAddr.port() != 0))
|
||||
connect(addr, sourceAddr);
|
||||
else
|
||||
{
|
||||
SocketAddress addr(_proxyConfig.host, _proxyConfig.port);
|
||||
connect(addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -536,6 +598,8 @@ StreamSocket HTTPClientSession::proxyConnect()
|
||||
proxyRequest.set(HTTPRequest::HOST, getHost());
|
||||
proxySession.proxyAuthenticateImpl(proxyRequest, _proxyConfig);
|
||||
proxySession.setKeepAlive(true);
|
||||
proxySession.setSourceAddress(_sourceAddress4);
|
||||
proxySession.setSourceAddress(_sourceAddress6);
|
||||
proxySession.sendRequest(proxyRequest);
|
||||
proxySession.receiveResponse(proxyResponse);
|
||||
if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
|
||||
|
||||
@@ -203,6 +203,13 @@ void HTTPSession::connect(const SocketAddress& address)
|
||||
}
|
||||
|
||||
|
||||
void HTTPSession::connect(const SocketAddress& targetAddress, const SocketAddress& sourceAddress)
|
||||
{
|
||||
_socket.bind(sourceAddress, true);
|
||||
connect(targetAddress);
|
||||
}
|
||||
|
||||
|
||||
void HTTPSession::abort()
|
||||
{
|
||||
_socket.shutdown();
|
||||
|
||||
@@ -112,6 +112,16 @@ StreamSocket& StreamSocket::operator = (StreamSocket&& socket)
|
||||
|
||||
#endif // POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
|
||||
void StreamSocket::bind(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
|
||||
{
|
||||
if (address.family() == IPAddress::IPv4)
|
||||
impl()->bind(address, reuseAddress);
|
||||
else
|
||||
impl()->bind6(address, reuseAddress, ipV6Only);
|
||||
}
|
||||
|
||||
|
||||
void StreamSocket::connect(const SocketAddress& address)
|
||||
{
|
||||
impl()->connect(address);
|
||||
|
||||
Reference in New Issue
Block a user