Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

connectionhttpproxy.cpp

00001 /*
00002   Copyright (c) 2004-2008 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,
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 // FIXME check return value?
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 // FIXME check return value?
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* /*connection*/,
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* /*connection*/ )
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* /*connection*/,
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 }

Generated on Mon Jun 23 10:50:18 2008 for gloox by  doxygen 1.4.1