mgsingletask.cpp

来自「一款LINUX下的下载软件」· C++ 代码 · 共 878 行 · 第 1/2 页

CPP
878
字号
/***************************************************************************
*            mgsingletask.cpp
*
*  Thu Sep  7 19:46:43 2006
*  Copyright  2006  liubin, China
*  Email multiget@gmail.com
****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef WIN32
#include <winsock2.h>
#endif

#include "mgsingletask.h"
#include "mgfilemanager.h"
#include "mgurlparser.h"
#include "showtablewindow.h" //for ui feedback
#include "threadinfowindow.h"
#include "taskmanager.h" //for ui feedback
#include "mainframe.h"
#include "mgapp.h"

#include "mgftpants.h"
#include "mghttpants.h"
#include "mgftpinfo.h"
#include "mghttpinfo.h"
//#include "mgtaskinit.h"
#include "proants.h"

#include <string>
#define  _MGSTR(s) wxGetApp().GetStr(s)
using namespace std;
extern void gfTaskLog( int ntaskid, std::string info, _MSGTYPE ntype, int ntime );
CMgSingleTask::CMgSingleTask(
    CTaskManager* parent,
    std::string url,
    std::string savepath,
    std::string savename,
    int taskid,
    int ants,
    int retry,
    int retrywait,
    std::string refer
)
{
    m_pFM = NULL;

    for ( int i = 0;i < 10;i++ )
    {
        m_pAnts[ i ] = NULL;
    }

    m_pShowTableWin = NULL;
    m_pThreadInfoWin = NULL;

    m_pFtpInfo = NULL;
    m_pHttpInfo = NULL;

    m_pParent = parent;
    m_nFileLen = -1;
    m_nTaskID = taskid;

    m_nRetry = retry;
    m_nRetryWait = retrywait;
    m_nError = 0;
    m_bUI = false;

    m_nMsgOutThreadId = 0;
    m_nLastFinishByte = 0L;


    m_sFilename = savename;
    m_sUrl = url;
    m_Refer = refer;
    m_sSavePath = savepath;
    m_nRunningAnts = 0;
    m_nStatus = _TASK_RUNNING;

    if ( ants < 0 )
        m_nAnts = 1;
    else if ( ants > 10 )
        m_nAnts = 10;
    else
        m_nAnts = ants;

    pthread_mutex_init ( &m_AntsMutex, NULL );

    pthread_mutex_init ( &m_QuitMutex, NULL );

    //socks proxy
    m_bUseProxy = false;

    m_ProxyPort = 0;

    m_ProxyVersion = V5;

    //HTTP proxy
    m_bUseHttpProxy = false;

    m_HttpProxyPort = 0;

    //FTP proxy
    m_bUseFtpProxy = false;

    m_FtpProxyPort = 0;

    m_bInitAlive = false;

    m_InitThread = NULL;	m_bInitAnts = false;
}

CMgSingleTask::~CMgSingleTask()
{
	
    pthread_mutex_lock( &m_QuitMutex );
	
    pthread_cancel( m_nInitThread );

    pthread_join( m_nInitThread, NULL );

    pthread_mutex_unlock( &m_QuitMutex );
	

	
    if ( m_pFM != NULL )
        m_pFM->Stop();

    for ( int i = 0;i < 10;i++ )
    {
        if ( m_pAnts[ i ] != NULL )
        {
            delete m_pAnts[ i ];
            m_pAnts[ i ] = NULL;
        }
    }

    if ( m_pFM != NULL )
    {
        delete m_pFM;
        m_pFM = NULL;
    }

    if ( m_pFtpInfo != NULL )
    {
        delete m_pFtpInfo;
        m_pFtpInfo = NULL;
    }

    if ( m_pHttpInfo != NULL )
    {
        delete m_pHttpInfo;
        m_pHttpInfo = NULL;
    }

}

void CMgSingleTask::ThreadQuit( int tid )
{

    pthread_mutex_lock( &m_AntsMutex );

    --m_nRunningAnts;

    if ( m_nRunningAnts <= 0 )
    {
        //get last filesize from fm,sometime can't get the size ahead

        if ( m_pFM->IsTaskFinish( m_nFileLen ) )
            FinishTask( _TASK_FINISH );
        else
            FinishTask( _TASK_ERROR );
    }

    pthread_mutex_unlock( &m_AntsMutex );
}

//swap to the init thread
void* CMgSingleTask::SwapInitThread( void* pthis )
{
    ((CMgSingleTask*)pthis)->InitThread();
    return NULL;
}

void CMgSingleTask::FinishTask( _SINGLE_TASK_STATUS status )
{
    m_nStatus = status;
    LogError(); //记录一些日志,有利于查找问题

    pthread_mutex_lock( &m_QuitMutex );

    wxCommandEvent event( mgEVT_TASK_FINISH, m_nTaskID );
    MainFrame *mainwin = ( MainFrame* ) ( wxGetApp().GetTopWindow() );

    mainwin->AddPendingEvent( event );
    //wxPostEvent( mainwin, event );
    pthread_mutex_unlock( &m_QuitMutex );

}

void CMgSingleTask::InitThread()
{
    OutMsg( -1, _MGSTR ( _S_SINGLETASK_JOBRUN ), MSG_INFO );

    pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );

    CUrlParser upar;

    if ( !m_Refer.empty() )
        upar.SetRefer( m_Refer );

    int oldstate;

    vector<string> cookie; //for http

again:

    OutMsg( -1, _MGSTR ( _S_SINGLETASK_ANALYSISURL ), MSG_INFO );

    if ( !upar.SetUrl( m_sUrl ) )
    {
        OutMsg( -1, _MGSTR ( _S_SINGLETASK_NOTSUPPORTURL ) + m_sUrl, MSG_ERROR );
        FinishTask( _TASK_ERROR );
        pthread_exit( 0 );
    }

    OutMsg( -1, _MGSTR ( _S_SINGLETASK_TASKURLOK ), MSG_INFO );
    //任务参数
    m_Server = upar.GetServer();

    m_ServerPort = upar.GetPort();

    m_Username = upar.GetUser();

    m_Password = upar.GetPass();

    m_EscFilePathName = upar.GetEscFilePathName(); //文件名


    if ( upar.GetUrlType() == FTP_PROTOCOL )   //ftp
    {
        OutMsg( -1, _MGSTR( _S_SINGLETASK_URLISFTP ), MSG_INFO );

        m_pFtpInfo = new CMgFtpInfo(
                         this,
                         m_sUrl,
                         m_nRetry,
                         m_nRetryWait,
                         -1
                     );
        //set proxy here

        if ( m_bUseProxy )
        {
            OutMsg( -1, _MGSTR ( _S_SINGLETASK_USESOCKSPROXY ), MSG_INFO );
            m_pFtpInfo->SetProxy( m_Proxy, m_ProxyPort, m_ProxyUser, m_ProxyPass, m_ProxyVersion );

        }

        if ( m_bUseFtpProxy )
        {
            OutMsg( -1, _MGSTR ( _S_SINGLETASK_USEFTPPROXY ), MSG_INFO );
            m_pFtpInfo->SetFtpProxy( m_FtpProxy, m_FtpProxyPort );
        }

        //go

        if ( !m_pFtpInfo->GetInfo() )
        { //error when get info. 2006/09/21

            OutMsg( -1, _MGSTR ( _S_SINGLETASK_GETFILEINFOERROR ), MSG_ERROR );
            pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );
            delete m_pFtpInfo;
            m_pFtpInfo = NULL;
            pthread_setcancelstate ( oldstate, NULL );
            FinishTask( _TASK_ERROR );
            pthread_exit( 0 );
        }

        m_nFileLen = m_pFtpInfo->FileSize();
        bool bresume = m_pFtpInfo->IsResume();

        pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );
        delete m_pFtpInfo;
        m_pFtpInfo = NULL;
        pthread_setcancelstate ( oldstate, NULL );


        if ( m_nFileLen == -1 || !bresume )
        {
            if ( m_nFileLen == -1 )
            {
                OutMsg( -1, _MGSTR ( _S_SINGLETASK_NOFILELENGTH ), MSG_WARNNING );
            }

            if ( !bresume )
            {
                OutMsg( -1, _MGSTR ( _S_SINGLETASK_NOTSUPPORTRESUME ), MSG_WARNNING );
            }

            m_nAnts = 1;
            //FinishTask(_TASK_ERROR);
            //InitThreadQuit();
        }


    } //main url ftp
    else if ( upar.GetUrlType() == HTTP_PROTOCOL )
    { //http
        OutMsg( -1, _MGSTR ( _S_SINGLETASK_URLISHTTP ), MSG_INFO );

        m_pHttpInfo =
            new CMgHttpInfo(
                this,
                m_sUrl,
                m_nRetry,
                m_nRetryWait,
                upar.GetRefer(),
                -1
            );
        //if need proxy, make here

        if ( m_bUseProxy )
        {
            OutMsg( -1, _MGSTR ( _S_SINGLETASK_USESOCKSPROXY ), MSG_INFO );
            m_pHttpInfo->SetProxy( m_Proxy, m_ProxyPort, m_ProxyUser, m_ProxyPass, m_ProxyVersion );

        }

        if ( m_bUseHttpProxy )
        {
            OutMsg( -1, _MGSTR ( _S_SINGLETASK_USEHTTPPROXY ), MSG_INFO );
            m_pHttpInfo->SetHttpProxy( m_HttpProxy, m_HttpProxyPort );
        }

        if ( !m_pHttpInfo->GetInfo() )
        { //error when get info.

            OutMsg( -1, _MGSTR ( _S_SINGLETASK_GETFILEINFOERROR ), MSG_ERROR );
            pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );
            delete m_pHttpInfo;
            m_pHttpInfo = NULL;
            pthread_setcancelstate ( oldstate, NULL );
            FinishTask( _TASK_ERROR );
            pthread_exit( 0 );
        }

        if ( m_pHttpInfo->IsRedirect() )
        {
            upar.SetRefer( m_sUrl );
            m_sUrl = m_pHttpInfo->GetRedirect();

            pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );
            delete m_pHttpInfo;
            m_pHttpInfo = NULL;
            pthread_setcancelstate ( oldstate, NULL );
            //跳转后就不再用原来的名字了。

            if ( upar.SetUrl( m_sUrl ) )
            {
                if ( upar.GetFileName() != string( "" ) )
                    m_sFilename = upar.GetFileName();
            }

            goto again;
        }

        //		for( int coo=0; coo < m_pHttpInfo->GetCookieNum(); coo++)
        //		{
        //
        //			cookie.push_back( m_pHttpInfo->GetCookie( coo ) );
        //		}

        m_nFileLen = m_pHttpInfo->GetFileSize();

        pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );

        delete m_pHttpInfo;

        m_pHttpInfo = NULL;

        pthread_setcancelstate ( oldstate, NULL );

        if ( m_nFileLen == -1 )
        {
            OutMsg( -1, _MGSTR ( _S_SINGLETASK_NOFILELENGTH ), MSG_WARNNING );
            m_nAnts = 1;
        }


    } //http
    else
    {
        OutMsg( -1, _MGSTR ( _S_SINGLETASK_NOTSUPPORTURL ) + m_sUrl, MSG_ERROR );

        FinishTask( _TASK_ERROR );
        pthread_exit( 0 );
    }


    //create file manager
    pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );

    m_pFM = new CMgFileManager ( this, m_sUrl, m_sFilename, m_sSavePath, m_nFileLen, upar.GetRefer() );

    pthread_setcancelstate ( oldstate, NULL );

    //check file
    if ( !m_pFM->CheckFile() )
    {
        pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE, &oldstate );
        delete m_pFM;
        m_pFM = NULL;
        pthread_setcancelstate ( oldstate, NULL );
        FinishTask( _TASK_ERROR );
        pthread_exit( 0 );
    }

    //input mirror url
    std::vector<std::string>::const_iterator it;

⌨️ 快捷键说明

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