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