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

📄 downloading.cpp

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.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.
*/
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Downloading.h"
#include "GiftCommand.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

namespace KCeasyEngine {

// initial number of max sources. 0 is unlimited.
static const int INITIAL_MAX_SOURCES = 20;
// if there was no data transfer for this time look for new sources
static const int KEEP_ALIVE_TIMEOUT = 1000 * 60 * 10;

// class TDlSource
// public

unsigned int TDlSource::GetTimeLeft()
{
    if(Throughput.GetBps() == 0)
        return 0;

    return  (Size - Transmitted) / Throughput.GetBps();
}

// private

TDlSource::TDlSource()
:   State(New),
    Start(0),
    Size(0),
    Transmitted(0)
{
    User = new TUser();
}

TDlSource::~TDlSource()
{
    delete User;
}



// private

bool TDlSource::SetStateStr(const string& StateStr)
{
    if(StateStr == "Waiting")                   State = Waiting;
    else if(StateStr == "Paused")               State = Paused;
    else if(StateStr == "Queued (Remotely)")    State = QueuedRemote;
    else if(StateStr == "Queued")               State = QueuedLocal;
    else if(StateStr == "Active")               State = Active;
    else if(StateStr == "Complete")             State = Complete;
    else if(StateStr == "Cancelled (Remotely)") State = Cancelled;
    else if(StateStr == "Timed out")            State = Timeout;
    else {
        State = Unused;
        return false;
    }
    return true;
}

// class TDownload
// private

TDownload::TDownload(TEngine* ParentEngine, const THashSet* NHashes)
:   Engine(ParentEngine),
    Hashes(NULL),
    GiftId(0),
    MaxSources(INITIAL_MAX_SOURCES),
    SourcesSearch(NULL),
    State(New),
    FileSize(0),
    Transmitted(0),
    Cancelling(false)
{
    Hashes = new THashSet(NHashes);
    // set active on creation
    LastActiveTime = ::GetTickCount();
}

TDownload::~TDownload()
{
    delete Hashes;
    ClearSources();
}

void TDownload::ClearSources()
{
    LockSources();
    while(!Sources.empty()) {
        delete Sources.front();
        Sources.pop_front();
    }
    ReleaseSources();
}

bool TDownload::ProcessAddDownload(TGiftCommand* Cmd)
{
    if(Cmd->Name != "ADDDOWNLOAD")
        return false;

    Engine->LockDownloads();
    // update download
    GiftId = string_to_int(Cmd->Value);
    SaveFileName = Cmd->GetNode("file").Value;
    FileSize = string_to_int(Cmd->GetNode("size").Value);
    Transmitted = string_to_int(Cmd->GetNode("transmit").Value);
    // set mime type if not already set from search result in AddSource
    if(MimeType == "")
        MimeType = Cmd->GetNode("mime").Value;
    // HACK: get network from random source
    if(Cmd->NodeExists("SOURCE"))
        Network = ProtocolFromUrl(Cmd->GetNode("SOURCE").GetNode("url").Value);

    // notify UI if this download wasn't created by us
    if(State == New) {
        // always make state queued at first
        State = TDownload::Queued;
        Engine->ReleaseDownloads();
        Engine->SendCallback(CbcNewDownload,(void*)this);
        Engine->LockDownloads();
    }
    // always make state queued at first if not paused
    State = (Cmd->GetNode("state").Value == "Paused") ? Paused : Queued;

    // set active on creation
    LastActiveTime = ::GetTickCount();

    // set current file path
    string SavePath = Cmd->GetNode("path").Value;
    if(SavePath != "") {
        if (Engine->IsUsingLocalGift())
            SavePath = UnixToWindowsPath(SavePath);
        // decide where to save it
        if(IncomingPath == "")
            IncomingPath = SavePath;
        else if (IncomingPath != SavePath)
            CompletedPath = SavePath;
    }

    // erase all previous sources and add the reported ones
    LockSources();
    ClearSources();
    for(TGiftCommand::Iterator itr=Cmd->Nodes.begin();itr!=Cmd->Nodes.end();++itr) {
        if((*itr).Name == "SOURCE") {
            TDlSource* DlSource = new TDlSource();
            DlSource->SourceId = (*itr).GetNode("url").Value;
            DlSource->GetUser()->SetId((*itr).GetNode("user").Value);
            DlSource->Network = ProtocolFromUrl(DlSource->SourceId);
            DlSource->Start = string_to_int((*itr).GetNode("start").Value);
            DlSource->Size = string_to_int((*itr).GetNode("total").Value);
            DlSource->Transmitted = string_to_int((*itr).GetNode("transmit").Value);
            DlSource->SetStateStr((*itr).GetNode("statusgrl").Value);
            DlSource->ProtoState = (*itr).GetNode("status").Value;

            Sources.push_back(DlSource);
            ReleaseSources();
            Engine->ReleaseDownloads();
            // notify UI
            Engine->SendCallback(CbcDownloadAddSource,(void*)this,(void*)DlSource);
            Engine->LockDownloads();
            LockSources();
        }
    }
    ReleaseSources();
    Engine->ReleaseDownloads();

    return true;
}

bool TDownload::ProcessDelDownload(TGiftCommand* Cmd)
{
    if(Cmd->Name != "DELDOWNLOAD" || string_to_int(Cmd->Value) != GiftId)
        return false;

    Engine->LockDownloads();

    // update state
    switch(State) {
    case Completed: {
        // add file to shares if we have a path
        if(GetCompletedPath() != "") {
            TSharedFile* File = new TSharedFile();
            *File->Hashes = *GetHashes();
            File->FileName = FileFromPath(GetCompletedPath());
            File->FileDir = DirFromPath(GetCompletedPath());
            File->FileSize = GetFileSize();
            File->MimeType = GetMimeType();
            File->FileType = FileTypeFromMime(File->MimeType);
            File->MetaData = GetMetaData();

            Engine->GetShares()->AddFile(File);
            delete File;
        }
        break;
    }
    case Cancelled:
    case Failed: {
        break;
    }
    default: {
        // we should never get here
        if(GetTransmitted() == GetFileSize())
            State = Completed;
        else
            State = Cancelled;
        break;
    }
    }

    GiftId = 0; // giFT reuses old IDs so drop it
    LastActiveTime = 0;

    if(SourcesSearch) {
        SourcesSearch->Cancel();
        SourcesSearch->SetUData(NULL);
        SourcesSearch = NULL; // will be freed in TSearch::ProcessItem later
    }

    Engine->ReleaseDownloads();
    // notify UI
    Engine->SendCallback(CbcDownloadUpdate,(void*)this);

    return true;
}

bool TDownload::ProcessChgDownload(TGiftCommand* Cmd)
{
    if(Cmd->Name != "CHGDOWNLOAD" || string_to_int(Cmd->Value) != GiftId)
        return false;

    if(State == Cancelled || State == Completed || State == Failed)
        return false;

    Engine->LockDownloads();

    // update sources
    int TimeElapsed = string_to_int(Cmd->GetNode("elapsed").Value);
    LockSources();
    Throughput.Reset();
    for(TGiftCommand::Iterator itr=Cmd->Nodes.begin();itr!=Cmd->Nodes.end();++itr) {
        if((*itr).Name == "SOURCE") {
            // find matching source
            string SourceId = (*itr).GetNode("url").Value;
            TDownload::TSourceIterator sitr = Sources.begin();
            while(sitr != Sources.end() && (*sitr)->SourceId != SourceId)
                ++sitr;
            if(sitr == Sources.end())
                continue;
            // update source
            (*sitr)->Start = string_to_int((*itr).GetNode("start").Value);
            (*sitr)->Size = string_to_int((*itr).GetNode("total").Value);
            // throughput
            if((*sitr)->Transmitted == 0 || string_to_int((*itr).GetNode("transmit").Value) == 0)
                (*sitr)->Throughput.Reset();
            else /* if (TimeElapsed > 100) */ // require at least 100 msec sampling time to prevent outliners
                (*sitr)->Throughput.AddSample(string_to_int((*itr).GetNode("transmit").Value)-(*sitr)->Transmitted,TimeElapsed);

            Throughput.SetBps(Throughput.GetBps() + (*sitr)->Throughput.GetBps());
            (*sitr)->Transmitted = string_to_int((*itr).GetNode("transmit").Value);
            (*sitr)->SetStateStr((*itr).GetNode("statusgrl").Value);
            (*sitr)->ProtoState = (*itr).GetNode("status").Value;
        }
    }
    ReleaseSources();
    Transmitted = string_to_int(Cmd->GetNode("transmit").Value);

    // set current file path
    string SavePath = Cmd->GetNode("path").Value;
    if(SavePath != "") {
        if (Engine->IsUsingLocalGift())
            SavePath = UnixToWindowsPath(SavePath);
        // decide where to save it
        if(IncomingPath == "")
            IncomingPath = SavePath;
        else if (IncomingPath != SavePath)
            CompletedPath = SavePath;
    }

⌨️ 快捷键说明

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