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