connectionhttpproxy.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "gloox.h"
00016
00017 #include "connectionhttpproxy.h"
00018 #include "dns.h"
00019 #include "logsink.h"
00020 #include "prep.h"
00021 #include "base64.h"
00022 #include "util.h"
00023
00024 #include <string>
00025
00026 namespace gloox
00027 {
00028
00029 ConnectionHTTPProxy::ConnectionHTTPProxy( ConnectionBase* connection,
00030 const LogSink& logInstance,
00031 const std::string& server, int port )
00032 : ConnectionBase( 0 ), m_connection( connection ),
00033 m_logInstance( logInstance ), m_http11( false )
00034 {
00035
00036 prep::idna( server, m_server );
00037 m_port = port;
00038
00039 if( m_connection )
00040 m_connection->registerConnectionDataHandler( this );
00041 }
00042
00043 ConnectionHTTPProxy::ConnectionHTTPProxy( ConnectionDataHandler* cdh,
00044 ConnectionBase* connection,
00045 const LogSink& logInstance,
00046 const std::string& server, int port )
00047 : ConnectionBase( cdh ), m_connection( connection ),
00048 m_logInstance( logInstance )
00049 {
00050
00051 prep::idna( server, m_server );
00052 m_port = port;
00053
00054 if( m_connection )
00055 m_connection->registerConnectionDataHandler( this );
00056 }
00057
00058 ConnectionHTTPProxy::~ConnectionHTTPProxy()
00059 {
00060 delete m_connection;
00061 }
00062
00063 ConnectionBase* ConnectionHTTPProxy::newInstance() const
00064 {
00065 ConnectionBase* conn = m_connection ? m_connection->newInstance() : 0;
00066 return new ConnectionHTTPProxy( m_handler, conn, m_logInstance, m_server, m_port );
00067 }
00068
00069 void ConnectionHTTPProxy::setConnectionImpl( ConnectionBase* connection )
00070 {
00071 if( m_connection )
00072 delete m_connection;
00073
00074 m_connection = connection;
00075 }
00076
00077 ConnectionError ConnectionHTTPProxy::connect()
00078 {
00079 if( m_connection && m_handler )
00080 {
00081 m_state = StateConnecting;
00082 return m_connection->connect();
00083 }
00084
00085 return ConnNotConnected;
00086 }
00087
00088 void ConnectionHTTPProxy::disconnect()
00089 {
00090 m_state = StateDisconnected;
00091 if( m_connection )
00092 m_connection->disconnect();
00093 }
00094
00095 ConnectionError ConnectionHTTPProxy::recv( int timeout )
00096 {
00097 return m_connection ? m_connection->recv( timeout ) : ConnNotConnected;
00098 }
00099
00100 ConnectionError ConnectionHTTPProxy::receive()
00101 {
00102 return m_connection ? m_connection->receive() : ConnNotConnected;
00103 }
00104
00105 bool ConnectionHTTPProxy::send( const std::string& data )
00106 {
00107 return m_connection && m_connection->send( data );
00108 }
00109
00110 void ConnectionHTTPProxy::cleanup()
00111 {
00112 m_state = StateDisconnected;
00113
00114 if( m_connection )
00115 m_connection->cleanup();
00116 }
00117
00118 void ConnectionHTTPProxy::getStatistics( long int& totalIn, long int& totalOut )
00119 {
00120 if( m_connection )
00121 m_connection->getStatistics( totalIn, totalOut );
00122 else
00123 totalIn = totalOut = 0;
00124 }
00125
00126 void ConnectionHTTPProxy::handleReceivedData( const ConnectionBase* ,
00127 const std::string& data )
00128 {
00129 if( !m_handler )
00130 return;
00131
00132 if( m_state == StateConnecting )
00133 {
00134 m_proxyHandshakeBuffer += data;
00135 if( ( !m_proxyHandshakeBuffer.compare( 0, 12, "HTTP/1.0 200" )
00136 || !m_proxyHandshakeBuffer.compare( 0, 12, "HTTP/1.1 200" ) )
00137 && !m_proxyHandshakeBuffer.compare( m_proxyHandshakeBuffer.length() - 4, 4, "\r\n\r\n" ) )
00138 {
00139 m_proxyHandshakeBuffer = EmptyString;
00140 m_state = StateConnected;
00141 m_logInstance.dbg( LogAreaClassConnectionHTTPProxy,
00142 "http proxy connection established" );
00143 m_handler->handleConnect( this );
00144 }
00145 else if( !m_proxyHandshakeBuffer.compare( 9, 3, "407" ) )
00146 {
00147 m_handler->handleDisconnect( this, ConnProxyAuthRequired );
00148 m_connection->disconnect();
00149 }
00150 else if( !m_proxyHandshakeBuffer.compare( 9, 3, "403" )
00151 || !m_proxyHandshakeBuffer.compare( 9, 3, "404" ) )
00152 {
00153 m_handler->handleDisconnect( this, ConnProxyAuthFailed );
00154 m_connection->disconnect();
00155 }
00156 }
00157 else if( m_state == StateConnected )
00158 m_handler->handleReceivedData( this, data );
00159 }
00160
00161 void ConnectionHTTPProxy::handleConnect( const ConnectionBase* )
00162 {
00163 if( m_connection )
00164 {
00165 std::string server = m_server;
00166 int port = m_port;
00167 if( port == -1 )
00168 {
00169 const DNS::HostMap& servers = DNS::resolve( m_server, m_logInstance );
00170 if( !servers.empty() )
00171 {
00172 const std::pair< std::string, int >& host = *servers.begin();
00173 server = host.first;
00174 port = host.second;
00175 }
00176 }
00177 std::string message = "Requesting http proxy connection to " + server + ":"
00178 + util::int2string( port );
00179 m_logInstance.dbg( LogAreaClassConnectionHTTPProxy, message );
00180
00181 std::string os = "CONNECT " + server + ":" + util::int2string( port ) + " HTTP/1."
00182 + util::int2string( m_http11 ? 1 : 0 ) + "\r\n"
00183 "Host: " + server + "\r\n"
00184 "Content-Length: 0\r\n"
00185 "Proxy-Connection: Keep-Alive\r\n"
00186 "Pragma: no-cache\r\n"
00187 "User-Agent: gloox/" + GLOOX_VERSION + "\r\n";
00188
00189 if( !m_proxyUser.empty() && !m_proxyPwd.empty() )
00190 {
00191 os += "Proxy-Authorization: Basic " + Base64::encode64( m_proxyUser + ":" + m_proxyPwd )
00192 + "\r\n";
00193 }
00194 os += "\r\n";
00195
00196 if( !m_connection->send( os ) )
00197 {
00198 m_state = StateDisconnected;
00199 if( m_handler )
00200 m_handler->handleDisconnect( this, ConnIoError );
00201 }
00202 }
00203 }
00204
00205 void ConnectionHTTPProxy::handleDisconnect( const ConnectionBase* ,
00206 ConnectionError reason )
00207 {
00208 m_state = StateDisconnected;
00209 m_logInstance.dbg( LogAreaClassConnectionHTTPProxy, "HTTP Proxy connection closed" );
00210
00211 if( m_handler )
00212 m_handler->handleDisconnect( this, reason );
00213 }
00214
00215 }