📄 tunnel.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 + -