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