clientthread.cpp

来自「著名的SecureBlackBox控件完整源码」· C++ 代码 · 共 549 行 · 第 1/2 页

CPP
549
字号
//---------------------------------------------------------------------------


#pragma hdrstop

#include "ClientThread.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

//---------------------------------------------------------------------------
TClientThread::TClientThread(const AnsiString AHost, int APort, const AnsiString Username, AnsiString Password,
          int AForwardPort, const AnsiString ADestHost, int ADestPort, bool NoGUI)
          : TThread(true)
{
    //  inherited Create(true);
    // creating tunnel list object
    FTunnelList = new TElSSHTunnelList(NULL);
    // creating and setting up tunnel object
    FTunnel = new TElLocalPortForwardSSHTunnel(NULL);
    FTunnel->Port = AForwardPort;
    FTunnel->ToHost = ADestHost;
    FTunnel->ToPort = ADestPort;
    FTunnel->TunnelList = FTunnelList;
    FTunnel->OnOpen = TunnelOpen;
    FTunnel->OnClose = TunnelClose;
    FTunnel->OnError = TunnelError;
    // creating and setting up SSH client object
    FSSHClient = new TElSSHClient(NULL);
    FSSHClient->UserName = Username;
    FSSHClient->Password = Password;
    FSSHClient->Versions = Sbsshcommon::TSSHVersions() <<sbSSH1 <<sbSSH2;
    FSSHClient->TunnelList = FTunnelList;
    FSSHClient->CloseIfNoActiveTunnels = false;
    FSSHClient->OnKeyValidate = SSHClientKeyValidate;
    FSSHClient->OnAuthenticationSuccess = SSHClientAuthSuccess;
    FSSHClient->OnAuthenticationFailed = SSHClientAuthFailed;
    FSSHClient->OnSend = SSHClientSend;
    FSSHClient->OnReceive = SSHClientReceive;
    FSSHClient->OnOpenConnection = SSHClientOpen;
    FSSHClient->OnCloseConnection = SSHClientClose;
    FSSHClient->OnError = SSHClientError;
    FSSHClient->ThreadSafe = false;
    // creating socket objects
    FTCPClient = new TIdTCPClient(NULL);
    FTCPClient->Host = AHost;
    FTCPClient->Port = APort;
    FTCPServer = new TIdTCPServer(NULL);
    FTCPServer->DefaultPort = AForwardPort;
    FTCPServer->OnConnect = TCPServerConnect;
    FTCPServer->OnExecute = TCPServerExecute;
    // creating channel list
    FChannels = new TList;
    FCS = new TCriticalSection;
    FGuiCS = new TCriticalSection;
    FNoGUI = NoGUI;
    Resume();
}
//---------------------------------------------------------------------------
__fastcall TClientThread::~TClientThread()
{
    delete FChannels;
    delete FTCPClient;
    delete FTCPServer;
    delete FSSHClient;
    delete FTunnel;
    delete FTunnelList;
    delete FCS;
    delete FGuiCS;
//    TThread::~TThread();
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::TunnelOpen(TObject* Sender, TElSSHTunnelConnection* TunnelConnection)
{
    TConnection* Conn;

    Log("SSH channel opened", false);
    Conn = (TConnection*)(TunnelConnection->Data);
    Conn->FChannel = TunnelConnection;
    Conn->FOutState = ocsActive;
    TunnelConnection->OnData = TunnelConnData;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::TunnelClose(TObject* Sender, TElSSHTunnelConnection* TunnelConnection)
{
    if (TunnelConnection->Data != NULL)
    {
        Log("SSH channel closed", false);
        ((TConnection*)(TunnelConnection->Data))->FOutState = ocsClosed;
        TunnelConnection->Data = NULL;
    }
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::TunnelError(TObject* Sender, int Error, void* Data)
{
    Log((AnsiString)"SSH tunnel error " + IntToStr(Error), false);
    ((TConnection*)(Data))->FOutState = ocsClosed;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::TunnelConnData(TObject* Sender, void* Buffer, int Size)
{
    ((TConnection*)(((TElSSHTunnelConnection*)(Sender))->Data))->WriteToSocketBuffer(Buffer, Size);
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientKeyValidate(TObject* Sender, TElSSHKey* ServerKey, bool &Validate)
{
    Log((AnsiString)"Server key received (fingerprint=" + DigestToStr(ServerKey->FingerprintMD5) + ")", false);
    Validate = true;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientAuthSuccess(TObject* Sender)
{
    Log("SSH authentication succeeded", false);
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientAuthFailed(TObject* Sender, int AuthenticationType)
{
    Log((AnsiString)"SSH authentication type " + IntToStr(AuthenticationType) + " failed", true);
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientSend(TObject* Sender, void* Buffer, int Size)
{
    try
    {
        FTCPClient->WriteBuffer(Buffer, Size, false);
    }
    catch(Exception &e)
    {
        FError = true;
    }
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientReceive(TObject* Sender, void* Buffer, int MaxSize, int &Written)
{
    try
    {
        Written = FTCPClient->Socket->Recv(Buffer, MaxSize);
    }
    catch(Exception &e)
    {
        Written = 0;
        FError = true;
    }
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientOpen(TObject* Sender)
{
    Log("SSH connection established", false);
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientClose(TObject* Sender)
{
    Log("SSH connection closed", false);
    FError = true;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::SSHClientError(TObject* Sender, int ErrorCode)
{
    Log((AnsiString)"SSH protocol error " + IntToStr(ErrorCode), true);
    FError = true;
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::TCPServerConnect(TIdPeerThread* AThread)
{
    TConnection* Conn;

    Log("Incoming connection accepted", false);
    Conn = new TConnection;
    Conn->FThread = AThread;
    AThread->Data = (TObject*)Conn;
    AThread->FreeOnTerminate = true;
    AThread->OnTerminate = TCPServerThreadTerminate;
    FCS->Acquire();
    try
    {
        FTunnel->Open(Conn);
    }
    __finally
    {
        FCS->Release();
    }
    if (!FNoGUI)
    {
        FGuiCS->Acquire();
        try
        {
            DoConnectionAdd(Conn);
        }
        __finally
        {
            FGuiCS->Release();
        }
    }
}
//---------------------------------------------------------------------------
void __fastcall TClientThread::TCPServerExecute(TIdPeerThread* AThread)
{
    char Buf[4096];
    int Read;
    AnsiString S;

    TConnection* Conn = (TConnection*)(AThread->Data);
    if ((AThread->Connection != NULL) && (AThread->Connection->Socket != NULL) &&
      (AThread->Connection->Socket->Binding != NULL))
    {
        Conn->FRemoteHost = AThread->Connection->Socket->Binding->PeerIP;
        Conn->FRemotePort = AThread->Connection->Socket->Binding->PeerPort;
    }
    while ((!AThread->Terminated) && (!((Conn->FInState == icsClosed) && (Conn->FOutState == ocsClosed))))
    {
        // processing socket endpoint
        if (Conn->FInState == icsActive)
        {
            if (AThread->Connection->Connected())
            {
                try
                {
                    AThread->Connection->CheckForGracefulDisconnect();
                    AThread->Connection->CheckForDisconnect();
                    // reading data from socket connection
                    if (AThread->Connection->InputBuffer->Size > 0)
                    {
                        //S = AThread->Connection->CurrentReadBuffer();
                        S = AThread->Connection->InputBuffer->Extract(AThread->Connection->InputBuffer->Size);
                        if (S.Length() > 0)
                            Conn->WriteToChannelBuffer(S.c_str(), S.Length());
                    }
                    // writing cached data to socket connection
                    do
                    {
                        Read = Conn->ReadFromSocketBuffer(Buf, 4096);
                        if (Read > 0)
                            AThread->Connection->WriteBuffer(Buf, Read);
                    } while (Read == 0);
                }
                catch(Exception &e)
                {
                    Log(e.Message, false);
                    Conn->FInState = icsClosing;
                    if ((AThread->Connection != NULL) &&
                        (AThread->Connection->Connected()) && (AThread->Connection->Socket != NULL) &&
                        (AThread->Connection->Socket->Binding != NULL))
                        AThread->Connection->Disconnect();
                }
            }
            else
                Conn->FInState = icsClosed;
        }

        // processing channel endpoint
        if (Conn->FOutState == ocsActive)
        {
            do
            {
                Read = Conn->ReadFromChannelBuffer(Buf, 4096);
                if (Read > 0)
                {
                    FCS->Acquire();
                    try
                    {
                        Conn->FChannel->SendData(Buf, Read);
                    }
                    __finally
                    {
                        FCS->Release();
                    }
                    Conn->FSent += Read;
                }
            } while (Read == 0);
        }

        // checking connection states
        if ((Conn->FInState == icsActive) && (Conn->FOutState == ocsClosed || Conn->FOutState == ocsClosing))
        {
            Conn->FInState = icsClosing;

⌨️ 快捷键说明

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