connectionhttpproxy.cpp

00001 /*
00002   Copyright (c) 2004-2007 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
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* /*connection*/,
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* /*connection*/ )
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* /*connection*/,
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 }

Generated on Sat Nov 10 08:50:27 2007 for gloox by  doxygen 1.5.3-20071008