connectionhttpproxy.cpp
/*
Copyright (c) 2004-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "gloox.h"
#include "connectionhttpproxy.h"
#include "dns.h"
#include "logsink.h"
#include "prep.h"
#include "base64.h"
#include "util.h"
#include <string>
namespace gloox
{
ConnectionHTTPProxy::ConnectionHTTPProxy( ConnectionBase* connection,
const LogSink& logInstance,
const std::string& server, int port )
: ConnectionBase( 0 ), m_connection( connection ),
m_logInstance( logInstance ), m_http11( false )
{
// FIXME check return value?
prep::idna( server, m_server );
m_port = port;
if( m_connection )
m_connection->registerConnectionDataHandler( this );
}
ConnectionHTTPProxy::ConnectionHTTPProxy( ConnectionDataHandler* cdh,
ConnectionBase* connection,
const LogSink& logInstance,
const std::string& server, int port )
: ConnectionBase( cdh ), m_connection( connection ),
m_logInstance( logInstance )
{
// FIXME check return value?
prep::idna( server, m_server );
m_port = port;
if( m_connection )
m_connection->registerConnectionDataHandler( this );
}
ConnectionHTTPProxy::~ConnectionHTTPProxy()
{
delete m_connection;
}
ConnectionBase* ConnectionHTTPProxy::newInstance() const
{
ConnectionBase* conn = m_connection ? m_connection->newInstance() : 0;
return new ConnectionHTTPProxy( m_handler, conn, m_logInstance, m_server, m_port );
}
void ConnectionHTTPProxy::setConnectionImpl( ConnectionBase* connection )
{
if( m_connection )
delete m_connection;
m_connection = connection;
}
ConnectionError ConnectionHTTPProxy::connect()
{
if( m_connection && m_handler )
{
m_state = StateConnecting;
return m_connection->connect();
}
return ConnNotConnected;
}
void ConnectionHTTPProxy::disconnect()
{
m_state = StateDisconnected;
if( m_connection )
m_connection->disconnect();
}
ConnectionError ConnectionHTTPProxy::recv( int timeout )
{
return m_connection ? m_connection->recv( timeout ) : ConnNotConnected;
}
ConnectionError ConnectionHTTPProxy::receive()
{
return m_connection ? m_connection->receive() : ConnNotConnected;
}
bool ConnectionHTTPProxy::send( const std::string& data )
{
return m_connection && m_connection->send( data );
}
void ConnectionHTTPProxy::cleanup()
{
m_state = StateDisconnected;
if( m_connection )
m_connection->cleanup();
}
void ConnectionHTTPProxy::getStatistics( long int& totalIn, long int& totalOut )
{
if( m_connection )
m_connection->getStatistics( totalIn, totalOut );
else
totalIn = totalOut = 0;
}
void ConnectionHTTPProxy::handleReceivedData( const ConnectionBase* /*connection*/,
const std::string& data )
{
if( !m_handler )
return;
if( m_state == StateConnecting )
{
m_proxyHandshakeBuffer += data;
if( ( !m_proxyHandshakeBuffer.compare( 0, 12, "HTTP/1.0 200" )
|| !m_proxyHandshakeBuffer.compare( 0, 12, "HTTP/1.1 200" ) )
&& !m_proxyHandshakeBuffer.compare( m_proxyHandshakeBuffer.length() - 4, 4, "\r\n\r\n" ) )
{
m_proxyHandshakeBuffer = EmptyString;
m_state = StateConnected;
m_logInstance.dbg( LogAreaClassConnectionHTTPProxy,
"HTTP proxy connection established" );
m_handler->handleConnect( this );
}
else if( !m_proxyHandshakeBuffer.compare( 9, 3, "407" ) )
{
m_handler->handleDisconnect( this, ConnProxyAuthRequired );
m_connection->disconnect();
}
else if( !m_proxyHandshakeBuffer.compare( 9, 3, "403" )
|| !m_proxyHandshakeBuffer.compare( 9, 3, "404" ) )
{
m_handler->handleDisconnect( this, ConnProxyAuthFailed );
m_connection->disconnect();
}
}
else if( m_state == StateConnected )
m_handler->handleReceivedData( this, data );
}
void ConnectionHTTPProxy::handleConnect( const ConnectionBase* /*connection*/ )
{
if( m_connection )
{
std::string server = m_server;
int port = m_port;
if( port == -1 )
{
const DNS::HostMap& servers = DNS::resolve( m_server, m_logInstance );
if( !servers.empty() )
{
const std::pair< std::string, int >& host = *servers.begin();
server = host.first;
port = host.second;
}
}
std::string message = "Requesting HTTP proxy connection to " + server + ":"
+ util::int2string( port );
m_logInstance.dbg( LogAreaClassConnectionHTTPProxy, message );
std::string os = "CONNECT " + server + ":" + util::int2string( port ) + " HTTP/1."
+ util::int2string( m_http11 ? 1 : 0 ) + "\r\n"
"Host: " + server + "\r\n"
"Content-Length: 0\r\n"
"Proxy-Connection: Keep-Alive\r\n"
"Pragma: no-cache\r\n"
"User-Agent: gloox/" + GLOOX_VERSION + "\r\n";
if( !m_proxyUser.empty() && !m_proxyPwd.empty() )
{
os += "Proxy-Authorization: Basic " + Base64::encode64( m_proxyUser + ":" + m_proxyPwd )
+ "\r\n";
}
os += "\r\n";
if( !m_connection->send( os ) )
{
m_state = StateDisconnected;
if( m_handler )
m_handler->handleDisconnect( this, ConnIoError );
}
}
}
void ConnectionHTTPProxy::handleDisconnect( const ConnectionBase* /*connection*/,
ConnectionError reason )
{
m_state = StateDisconnected;
m_logInstance.dbg( LogAreaClassConnectionHTTPProxy, "HTTP Proxy connection closed" );
if( m_handler )
m_handler->handleDisconnect( this, reason );
}
}
gloox::ConnectionBase::m_state
ConnectionState m_state
Definition connectionbase.h:155
gloox::ConnectionBase::port
int port() const
Definition connectionbase.h:121
gloox::ConnectionBase::server
const std::string & server() const
Definition connectionbase.h:115
gloox::ConnectionBase::m_port
int m_port
Definition connectionbase.h:161
gloox::ConnectionBase::m_handler
ConnectionDataHandler * m_handler
Definition connectionbase.h:152
gloox::ConnectionBase::m_server
std::string m_server
Definition connectionbase.h:158
gloox::ConnectionBase::ConnectionBase
ConnectionBase(ConnectionDataHandler *cdh)
Definition connectionbase.h:42
gloox::ConnectionDataHandler
This is an abstract base class to receive events from a ConnectionBase-derived object.
Definition connectiondatahandler.h:36
gloox::ConnectionHTTPProxy::~ConnectionHTTPProxy
virtual ~ConnectionHTTPProxy()
Definition connectionhttpproxy.cpp:58
gloox::ConnectionHTTPProxy::handleDisconnect
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)
Definition connectionhttpproxy.cpp:205
gloox::ConnectionHTTPProxy::recv
virtual ConnectionError recv(int timeout=-1)
Definition connectionhttpproxy.cpp:95
gloox::ConnectionHTTPProxy::cleanup
virtual void cleanup()
Definition connectionhttpproxy.cpp:110
gloox::ConnectionHTTPProxy::handleConnect
virtual void handleConnect(const ConnectionBase *connection)
Definition connectionhttpproxy.cpp:161
gloox::ConnectionHTTPProxy::handleReceivedData
virtual void handleReceivedData(const ConnectionBase *connection, const std::string &data)
Definition connectionhttpproxy.cpp:126
gloox::ConnectionHTTPProxy::disconnect
virtual void disconnect()
Definition connectionhttpproxy.cpp:88
gloox::ConnectionHTTPProxy::newInstance
virtual ConnectionBase * newInstance() const
Definition connectionhttpproxy.cpp:63
gloox::ConnectionHTTPProxy::connect
virtual ConnectionError connect()
Definition connectionhttpproxy.cpp:77
gloox::ConnectionHTTPProxy::setConnectionImpl
void setConnectionImpl(ConnectionBase *connection)
Definition connectionhttpproxy.cpp:69
gloox::ConnectionHTTPProxy::send
virtual bool send(const std::string &data)
Definition connectionhttpproxy.cpp:105
gloox::ConnectionHTTPProxy::ConnectionHTTPProxy
ConnectionHTTPProxy(ConnectionBase *connection, const LogSink &logInstance, const std::string &server, int port=-1)
Definition connectionhttpproxy.cpp:29
gloox::ConnectionHTTPProxy::receive
virtual ConnectionError receive()
Definition connectionhttpproxy.cpp:100
gloox::ConnectionHTTPProxy::getStatistics
virtual void getStatistics(long int &totalIn, long int &totalOut)
Definition connectionhttpproxy.cpp:118
gloox::DNS::resolve
static HostMap resolve(const std::string &service, const std::string &proto, const std::string &domain, const LogSink &logInstance)
Definition dns.cpp:83
gloox::DNS::HostMap
std::map< std::string, int > HostMap
Definition dns.h:68
gloox::LogSink
An implementation of log sink and source.
Definition logsink.h:39
gloox::Base64::encode64
const std::string encode64(const std::string &input)
Definition base64.cpp:38
gloox::prep::idna
bool idna(const std::string &domain, std::string &out)
Definition prep.cpp:107
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28
gloox::GLOOX_VERSION
const std::string GLOOX_VERSION
Definition gloox.cpp:119
gloox::ConnectionError
ConnectionError
Definition gloox.h:684
gloox::ConnNotConnected
@ ConnNotConnected
Definition gloox.h:715
gloox::ConnProxyAuthFailed
@ ConnProxyAuthFailed
Definition gloox.h:692
gloox::ConnProxyAuthRequired
@ ConnProxyAuthRequired
Definition gloox.h:690
gloox::ConnIoError
@ ConnIoError
Definition gloox.h:696
gloox::LogAreaClassConnectionHTTPProxy
@ LogAreaClassConnectionHTTPProxy
Definition gloox.h:1060
gloox::EmptyString
const std::string EmptyString
Definition gloox.cpp:124
gloox::StateDisconnected
@ StateDisconnected
Definition gloox.h:642
gloox::StateConnected
@ StateConnected
Definition gloox.h:644
gloox::StateConnecting
@ StateConnecting
Definition gloox.h:643