⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.cpp

📁 http代理程序
💻 CPP
字号:


/************************************
  REVISION LOG ENTRY
  Revision By: Alex Turc
  Revised on 6/15/00 1:54:13 PM
  Comments: Implementation of the HTTP tunnels related clases
 ************************************/

#include "StdAfx.h"
#include "tunnel.h"
#include "manager.h"
#include "common.h"

#include <sstream>
#include <map>
using namespace std;

#include "mylib/_str.h"
using namespace extension;


// Function name	: tunnel::tunnel
// Description	    : Constructor for a general tunnel
// Return type		: 
//##ModelId=3B79EDE500E9
tunnel::tunnel( a_ptr< sockstream > pskSource, a_ptr< sockstream > pskDestination, int iBufferSize /* = 2 * 1024 */ ) :
	m_pskSource( pskSource ), m_pskDestination( pskDestination ), m_lID(0)
{
	m_lID = clock();

	// Both sockets are set as non-blocking
	m_pskSource->set_blocking_mode( false );
	m_pskDestination->set_blocking_mode( false );

	// 2 Kb buffers
	m_vctBuffer_1.resize( iBufferSize );
	m_iContentSize_1 = 0;
	m_vctBuffer_2.resize( iBufferSize );
	m_iContentSize_2 = 0;
}

// Function name	: tunnel::~tunnel
// Description	    : Destructor for a tunnel
// Return type		: 
//##ModelId=3B79EDE500FD
tunnel::~tunnel()
{
	close();
}


// Function name	: tunnel::close
// Description	    : Close the tunnel
// Return type		: void 
//##ModelId=3B79EDE50108
void tunnel::close()
{
	m_pskSource->close();
	m_pskDestination->close();
}


// Function name	: tunnel::is_active
// Description	    : Returns true only if both connection are opened
// Return type		: void 
//##ModelId=3B79EDE50111
bool tunnel::is_active()
{
	return m_pskSource->is_open() && m_pskDestination->is_open();
}


// Function name	: tunnel::do_data_transfer
// Description	    : Makes data transfer through this tunnel
// Return type		: void
//##ModelId=3B79EDE5011B
void tunnel::do_data_transfer()
{
	int iReaded, iWritten;

	// Source ==> Destination

	iReaded = m_pskSource->rdbuf()->sgetn( m_vctBuffer_1.begin() + m_iContentSize_1, m_vctBuffer_1.size() - m_iContentSize_1 );
	if( iReaded < 0 )
	{
		if( m_iContentSize_1 == 0 )
		{
			close();
			return;
		}
	}
	else
		m_iContentSize_1 += iReaded;

	iWritten = m_pskDestination->rdbuf()->sputn( m_vctBuffer_1.begin(), m_iContentSize_1 );	
	if( iWritten < 0 )		
	{
		close();
		return;
	}
	else
		m_iContentSize_1 -= iWritten;

	
	// Destination ==> Source	
	
	iReaded = m_pskDestination->rdbuf()->sgetn( m_vctBuffer_2.begin() + m_iContentSize_2, m_vctBuffer_2.size() - m_iContentSize_2 );
	if( iReaded < 0 )
	{
		if( m_iContentSize_2 == 0 )
		{
			close();
			return;
		}
	}
	else
		m_iContentSize_2 += iReaded;

	iWritten = m_pskSource->rdbuf()->sputn( m_vctBuffer_2.begin(), m_iContentSize_2 );	
	if( iWritten < 0 )
	{
		close();
		return;
	}
	else
		m_iContentSize_2 -= iWritten;
}



// Function name	: tunnel_constructor::tunnel_constructor
// Description	    : Tunnel constructor base class initialization
// Return type		: 
// Argument         : manager* pManager
// Argument         : a_ptr< sockstream > pskSource
// Argument         : const char* szDestinationAddress
// Argument         : int iDestinationPort
//##ModelId=3B79EDE50180
tunnel_constructor::tunnel_constructor( manager* pManager, a_ptr< sockstream > pskSource, const char* szDestinationAddress, int iDestinationPort ) :
	m_pManager( pManager ), m_pskSource( pskSource ), m_strDestinationAddress( szDestinationAddress ), m_iDestinationPort( iDestinationPort )
{
}

//##ModelId=3B79EDE50193
tunnel_constructor::~tunnel_constructor()
{
	close();
}

// Function name	: tunnel_constructor::stop
// Description	    : Stops the tunnl constructor
// Return type		: void 
//##ModelId=3B79EDE501A7
void tunnel_constructor::stop()
{
	close();
	thread::stop();
}


// Function name	: tunnel_constructor::close
// Description	    : Closes any active connection pn this tunnel constructor
// Return type		: void 
//##ModelId=3B79EDE5019D
void tunnel_constructor::close()
{
	m_pskSource->close();
	m_pskDestination->close();
}


// Function name	: direct_tunnel_constructor::direct_tunnel_constructor
// Description	    : Initialization for direct tunnel constructor
// Return type		: 
// Argument         : manager* pManager
// Argument         : a_ptr< sockstream > pskSource
// Argument         : const char* szDestinationAddress
// Argument         : int iDestinationPort
//##ModelId=3B79EDE5025C
direct_tunnel_constructor::direct_tunnel_constructor( manager* pManager, a_ptr< sockstream > pskSource, const char* szDestinationAddress, int iDestinationPort ) :
	tunnel_constructor( pManager, pskSource, szDestinationAddress, iDestinationPort )
{
}


// Function name	: direct_tunnel_constructor::run
// Description	    : Construct a direct tunnel
// Return type		: unsigned long 
//##ModelId=3B79EDE5026F
unsigned long direct_tunnel_constructor::run()
{
	try
	{
		gpEventLog->log_event( event_log::event_type_information, "Direct tunnel request. Destination %s:%d.", m_strDestinationAddress.c_str(), m_iDestinationPort );

		m_pskDestination = new sockstream( m_strDestinationAddress.c_str(), m_iDestinationPort );
		if( m_pskDestination->fail() )
			throw_exception( tunnel_exception, tunnel_exception::exception_code_generic, "Failed to open direct connection" );

		// Add the tunnel to the manager's list
		a_ptr< tunnel > pTunnel = new tunnel( m_pskSource, m_pskDestination  );
		m_pManager->add_tunnel( pTunnel );

		gpEventLog->log_event( event_log::event_type_information, "Direct tunnel %#.8LX constructed. Destination %s:%d", pTunnel->m_lID, m_strDestinationAddress.c_str(), m_iDestinationPort );
	}
	catch( exception e )
	{
		gpEventLog->log_event( event_log::event_type_warning, "Tunnel failed. %s. Destination %s:%d", e.what(), m_strDestinationAddress.c_str(), m_iDestinationPort );
	}
	
	return 0;
}


// Function name	: proxy_tunnel_constructor::proxy_tunnel_constructor
// Description	    : Initialization for proxy tunnel constructor
// Return type		: 
// Argument         :  manager* pManager
// Argument         : a_ptr< sockstream > pskSource
// Argument         : const char* szProxyAddress
// Argument         : int iProxyPort
// Argument         : const char* szDestinationAddress
// Argument         : int iDestinationPort
//##ModelId=3B79EDE502AC
proxy_tunnel_constructor::proxy_tunnel_constructor( manager* pManager, a_ptr< sockstream > pskSource, const char* szProxyAddress, int iProxyPort, const char* szDestinationAddress, int iDestinationPort ) :
	tunnel_constructor( pManager, pskSource, szDestinationAddress, iDestinationPort ), m_strProxyAddress( szProxyAddress ), m_iProxyPort( iProxyPort )
{
}


// Function name	: proxy_tunnel_constructor::run
// Description	    : Construct a direct tunnel
// Return type		: unsigned long 
//##ModelId=3B79EDE502C0
unsigned long proxy_tunnel_constructor::run()
{
	try
	{
		gpEventLog->log_event( event_log::event_type_information, "Proxy tunnel request. Destination %s:%d, proxy: %s:%d", m_strDestinationAddress.c_str(), m_iDestinationPort, m_strProxyAddress.c_str(), m_iProxyPort );

		// Connect to proxy
		m_pskDestination = new sockstream( m_strProxyAddress.c_str(), m_iProxyPort );
		if( m_pskDestination->fail() )
			throw_exception( tunnel_exception, tunnel_exception::exception_code_generic, "Failed to open connection to proxy" );

		// Send the connect request
		(*m_pskDestination) << "CONNECT" << " " << m_strDestinationAddress.c_str() << ":" << m_iDestinationPort << " " << "HTTP/1.1" << "\r\n";
		(*m_pskDestination) << "\r\n";

		// Read the response from the proxy
		string strToken;
		*m_pskDestination >> strToken >> strToken;
		if( m_pskDestination->fail() )
			throw_exception( tunnel_exception, tunnel_exception::exception_code_generic, "Connection to proxy failed when trying to send the request" );

		if( strToken != "200" )
			throw_exception( tunnel_exception, tunnel_exception::exception_code_generic, "Connection to destination failed" );

		m_pskDestination->ignore( INT_MAX, '\n' );

		// Ignore the empty line in HTTP protocol
		m_pskDestination->ignore( INT_MAX, '\n' );

		// Create and add tunnel to the list of active tunnels
		a_ptr< tunnel > pTunnel = new tunnel( m_pskSource, m_pskDestination );
		m_pManager->add_tunnel( pTunnel );

		gpEventLog->log_event( event_log::event_type_information, "Proxy tunnel %#.8LX constructed. Destination %s:%d, proxy: %s:%d.", pTunnel->m_lID, m_strDestinationAddress.c_str(), m_iDestinationPort, m_strProxyAddress.c_str(), m_iProxyPort );
	}
	catch( exception e )
	{
		gpEventLog->log_event( event_log::event_type_warning, "Tunnel failed. %s. Destination %s:%d, proxy: %s:%d", e.what(), m_strDestinationAddress.c_str(), m_iDestinationPort, m_strProxyAddress.c_str(), m_iProxyPort );
	}

	return 0;
}


// Function name	: tunnel_request_listener::tunnel_request_listener
// Description	    : Initialization of a tunnel acceptor class
// Return type		: 
// Argument         : manager* pManager
// Argument         : const tunnel_cfg& c
//##ModelId=3B79EDE50343
tunnel_request_listener::tunnel_request_listener( manager* pManager, const tunnel_cfg& c )
{
	m_pManager = pManager;
	*static_cast< tunnel_cfg* >( this ) = c;
}



// Function name	: tunnel_request_listener::~tunnel_request_listener
// Description	    : Destroys the tunnel request listener
// Return type		: 
//##ModelId=3B79EDE5034D
tunnel_request_listener::~tunnel_request_listener()
{
}

// Function name	: tunnel_request_listener::stop
// Description	    : 
// Return type		: void 
//##ModelId=3B79EDE50361
void tunnel_request_listener::stop()
{
	// Close the server socket
	m_pskServerSocket->close();

	// Stop the thread
	thread::stop();
}


// Function name	: tunnel_request_listener::run
// Description	    : 
// Return type		: unsigned long 
//##ModelId=3B79EDE50356
unsigned long tunnel_request_listener::run()
{
	try
	{
		// Open the socket
		m_pskServerSocket = new server_socket< char >( m_iSourcePort );

		if( use_proxy() )
			gpEventLog->log_event( event_log::event_type_information, "Tunnel request listener created: %d->%s:%d->%s:%d", m_iSourcePort, m_strProxyAddress.c_str(), m_iProxyPort, m_strDestinationAddress.c_str(), m_iDestinationPort );
		else
			gpEventLog->log_event( event_log::event_type_information, "Tunnel request listener created: %d->%s:%d", m_iSourcePort, m_strDestinationAddress.c_str(), m_iDestinationPort );


		while( !m_bTerminateRequest )
		{
			try
			{
				// Accept a connection
				basic_sockbuf< char >* pSocketBuffer = m_pskServerSocket->accept();

				try
				{	
					a_ptr< tunnel_constructor > pConstructor;
				
					// Create the appropiate tunnel constructor
					if( use_proxy() )
						pConstructor = new proxy_tunnel_constructor( m_pManager, new sockstream( pSocketBuffer ), m_strProxyAddress.c_str(), m_iProxyPort, m_strDestinationAddress.c_str(), m_iDestinationPort );
					else
						pConstructor = new direct_tunnel_constructor( m_pManager, new sockstream( pSocketBuffer ), m_strDestinationAddress.c_str(), m_iDestinationPort );

					pConstructor->resume();

					// Add the constructor to the list of constructors
					m_pManager->add_tunnel_constructor( pConstructor );
				}
				catch( ... )
				{
					gpEventLog->log_event( event_log::event_type_warning, "Incomming tunnel couldn't be handled" );
				}
			}
			catch( socket_exception e )
			{
				gpEventLog->log_event( event_log::event_type_warning, "Accept operation on port %d on local host failed. %s", m_iSourcePort, e.what() );
			}
		}
	}
	catch( ... )
	{
		gpEventLog->log_event( event_log::event_type_warning, "Fatal exception occured on tunnel_request_listener. Local port: %d", m_iSourcePort );
	}

	if( use_proxy() )
		gpEventLog->log_event( event_log::event_type_information, "Tunnel request listener destroyed: %d->%s:%d->%s:%d", m_iSourcePort, m_strProxyAddress.c_str(), m_iProxyPort, m_strDestinationAddress.c_str(), m_iDestinationPort );
	else
		gpEventLog->log_event( event_log::event_type_information, "Tunnel request listener destroyed: %d->%s:%d", m_iSourcePort, m_strDestinationAddress.c_str(), m_iDestinationPort );



	return 0;
}


// Function name	: tunnel_request_listener::use_proxy
// Description	    : Returns true if the tunnel is made through a proxy or false if not
// Return type		: bool 
//##ModelId=3B79EDE50392
bool tunnel_request_listener::use_proxy()
{
	return m_strProxyAddress.size() > 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -