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

📄 downloadmanager.cpp

📁 FreeAMP(MP3播放)程序源代码-用来研究MP3解码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        }
        
        //char   path[255];
        //uint32 length = sizeof(path);
        //URLToFilePath(url, path, &length);
        //unlink(path);
    }

    return result;
}

// Utility Functions
bool DownloadManager::IsEmpty()
{
    bool result;
    m_mutex.Acquire();

    result = m_itemList.empty();

    m_mutex.Release();
    return result;
}

uint32 DownloadManager::CountItems()
{
    uint32 result;
    m_mutex.Acquire();

    result = m_itemList.size();

    m_mutex.Release();
    return result;
}

DownloadItem* DownloadManager::ItemAt(uint32 index)
{
    DownloadItem* result = NULL;
    m_mutex.Acquire();
    
    index = CheckIndex(index);

    if(index != kInvalidIndex)
    {
        result = m_itemList[index];
    }
    
    m_mutex.Release();
    return result;
}

uint32 DownloadManager::IndexOf(DownloadItem* item)
{
    return InternalIndexOf(&m_itemList, item);
}

uint32 DownloadManager::InternalIndexOf(vector<DownloadItem*>* list,
                                        DownloadItem* item)
{
    uint32 result = kInvalidIndex;
    uint32 index = 0;
    uint32 size = 0;

    assert(list);
    assert(item);

    if(list && item)
    {
        size = list->size();

        for(index = 0; index < size; index++)
        {
            if(item == (*list)[index])
            {
                result = index;
                break;
            }
        }
    }
    
    return result;
}

bool DownloadManager::HasItem(DownloadItem* item)
{
    return (IndexOf(item) != kInvalidIndex);
}

// Internal functions

inline uint32 DownloadManager::CheckIndex(uint32 index)
{
	// If we're dealing with a bogus index then set it to -1.
	if(index >= CountItems())
    {
		index = kInvalidIndex;
    }

	return index;
}

DownloadItem* DownloadManager::GetNextQueuedItem()
{
    int           i, total = 0;

    if (m_downloadIndex < 0 || m_downloadIndex >= (int)m_itemList.size())
        m_downloadIndex = 0;

    for(i = m_downloadIndex, total = 0; i < (int)m_itemList.size(); 
        i = (i + 1) % m_itemList.size(), total++)
    {
        if (total >= (int)m_itemList.size())
            return NULL;
           
        if (m_itemList[i]->GetState() == kDownloadItemState_Queued)
        {
            m_downloadIndex++;
            return m_itemList[i];
        }
    }
    
    return NULL;
}

static int32 GetContentLengthFromHeader(const char* buffer)
{
    int32 result = -1;

    char* cp = strstr(buffer, "Content-Length:");

    if(cp)
    {
        cp += strlen("Content-Length:") + 1;

        result = atoi(cp);
    }

    return result;
}

static void GetContentTimeFromHeader(const char* buffer, string &mTime)
{
    char* cp = strstr(buffer, "Last-Modified:");
    if(cp)
    {
        string::size_type pos;
        
        cp += strlen("Last-Modified:") + 1;
        mTime = string(cp);

        pos = mTime.find(string("\r"), 0);
        if (pos != string::npos)
           mTime.erase(pos, mTime.length() - 2);

        pos = mTime.find(string("\n"), 0);
        if (pos != string::npos)
           mTime.erase(pos, mTime.length() - 2);
    }
    else
        mTime = string("");
}


const uint8 kHttpPort = 80;
const uint32 kMaxHostNameLen = 64;
const uint32 kMaxURLLen = 1024;

static bool IsHTTPHeaderComplete(char* buffer, uint32 length)
{
    bool result = false;

    //if(length >= 4)
    //{
        //if( (buffer[0] == 'H' && buffer[1] == 'T' 
        //       && buffer[2] == 'T' && buffer[3] == 'P'))
        //{
            //cout << "buffer is HTTP" << endl;

            for(char* cp = buffer; cp < buffer + length; cp++)
            {
                if(!strncmp(cp, "\n\n", 2) || !strncmp(cp, "\r\n\r\n", 4))
                {
                    result = true;
                    break;
                }
            }
        //}
    //}

    return result;
}

Error DownloadManager::Download(DownloadItem* item)
{
    Error result = kError_InvalidParam;

    assert(item);
    if(item)
    {
        char hostname[kMaxHostNameLen + 1] = {0x00};
        char proxyname[kMaxURLLen + 1] = {0x00};
        unsigned short port;
        struct sockaddr_in  addr;
        struct hostent      host;
        SOCKET s = -1;
        char* file = NULL;
        char* destPath = NULL;
        bool useProxy;
        struct stat st;

        destPath = new char[_MAX_PATH];
        uint32 length = _MAX_PATH;

        m_context->prefs->GetPrefString(kSaveMusicDirPref, destPath, &length);

        strcat(destPath, DIR_MARKER_STR);
        strcat(destPath, item->DestinationFile().c_str());
        
        if(-1 != stat(destPath, &st))
        {
            if ((unsigned int)st.st_size >= item->GetTotalBytes())
            {
               if(destPath)
                   delete [] destPath;
               return kError_NoErr;    
            }
        }

        result = kError_ProtocolNotSupported;

        // where should we connect to?
        if(!strncasecmp(item->SourceURL().c_str(), "http://", 7))
        {
            int32 numFields;
            uint32 length;

            result = kError_NoErr;  

            m_context->prefs->GetPrefBoolean(kUseProxyPref, &useProxy);

            if(useProxy)
            {
                char proxy[kMaxURLLen + 1] = {0x00};

                length = sizeof(proxy);
                m_context->prefs->GetPrefString(kProxyHostPref, proxy, &length);

                numFields = sscanf(proxy, 
                                   "http://%[^:/]:%hu", proxyname, &port);

                sscanf(item->SourceURL().c_str(), 
                               "http://%[^:/]", hostname);

                //strncpy(proxyname, item->SourceURL().c_str(), kMaxURLLen);
                //proxyname[kMaxURLLen - 1] = 0;
                file = (char*)item->SourceURL().c_str();
            }
            else
            {
                numFields = sscanf(item->SourceURL().c_str(), 
                               "http://%[^:/]:%hu", hostname, &port);

                file = strchr(item->SourceURL().c_str() + 7, '/');
            }

            if(numFields < 1)
            {
                result = kError_InvalidURL;     
            }

            if(numFields < 2)
            {
                port = kHttpPort;
            }            
        }

        if(item->GetState() != kDownloadItemState_Downloading) 
            result = kError_UserCancel;

        // get hostname
        if(IsntError(result))
        {
            char* server = (*proxyname ? proxyname : hostname);
            struct hostent* hostByName;
            struct hostent  hostByIP;

            //*m_debug << "gethostbyname: " << hostname << endl;
            hostByName = gethostbyname(server);

            // On some stacks a numeric IP address
            // will not parse with gethostbyname.  
            // If that didn't work try to convert it as a
            // numeric address before giving up.
            if(!hostByName)
            {
                static unsigned long ip;
                static char *addr_ptr[2] = {(char*)&ip, NULL};

                if((int)(ip = inet_addr(server)) < 0) 
                    result =  kError_CantFindHost;
                else
                {
                    hostByIP.h_length = sizeof(uint32);
                    hostByIP.h_addrtype = AF_INET;
                    hostByIP.h_addr_list = (char**)&addr_ptr;
                    hostByName = &hostByIP;
                }
            }

            if(IsntError(result))
            {
                memcpy(&host, hostByName, sizeof(struct hostent));
            }

            if(item->GetState() != kDownloadItemState_Downloading) 
                result = kError_UserCancel;
        }

        // open socket
        if(IsntError(result))
        {
            memset(&addr, 0x00, sizeof(struct sockaddr_in));
            memcpy(&addr.sin_addr, host.h_addr, host.h_length);
            addr.sin_family= host.h_addrtype;
            addr.sin_port= htons(port); 

            //*m_debug << "socket" << endl;

            s = socket(host.h_addrtype, SOCK_STREAM, 0);

            if(s < 0)
                result = kError_CantCreateSocket;

            if(item->GetState() != kDownloadItemState_Downloading)
                result = kError_UserCancel;
        }

        // connect and send request
        if(IsntError(result))
        {
            Error err;
            int   ret;
            
            err = Connect(s, (const struct sockaddr*)&addr, ret, item);
            if (IsError(err))
                result = kError_UserCancel;
                
            if (ret < 0)    
                result = kError_ConnectFailed;

            if(item->GetState() != kDownloadItemState_Downloading)
                result = kError_UserCancel;

            if(IsntError(result))
            {
                const char* kHTTPQuery = "GET %s HTTP/1.1\r\n"
                                         "Host: %s\r\n"
                                         "Accept: */*\r\n" 
                                         "User-Agent: FreeAmp/%s\r\n";

                const char* kRange = "Range: bytes=%lu-\r\n";
                const char* kIfRange = "If-Range: %s\r\n";

                const char* kCookie = "Cookie: %s\r\n";

                // the magic 256 is enough for a time field that
                // we got from the server
                char* query = new char[ strlen(kHTTPQuery) + 
                                        strlen(file) +
                                        strlen(hostname) +
                                        strlen(FREEAMP_VERSION)+
                                        (item->GetBytesReceived() ? (strlen(kRange) + 256): 0 ) +
                                        (item->SourceCookie().size() ? (item->SourceCookie().size() + strlen(kCookie)): 0) +
                                        2];
            
                sprintf(query, kHTTPQuery, file, hostname, FREEAMP_VERSION);

                // do we need to request a range?
                if(item->GetBytesReceived())
                { 
                    if(-1 != stat(destPath, &st))
                    {
                        char* range = new char[strlen(kRange) + 256 + 1];

                        sprintf(range, kRange, item->GetBytesReceived());
                        strcat(query, range);

                        if (item->MTime().length() > 0)
                        {
                            sprintf(range, kIfRange, item->MTime().c_str());
                            strcat(query, range);
                        }
                        delete [] range;
                    }
                    else
                    {
                        item->SetBytesReceived(0);
                        item->SetMTime("");
                    }
                }

                if(item->SourceCookie().size())
                {
                    char* cookie = new char[strlen(kCookie) + item->SourceCookie().size() + 1];

                    sprintf(cookie, kCookie, item->SourceCookie().c_str());

                    strcat(query, cookie);

                    delete [] cookie;
                }
            
                strcat(query, "\n");
                
                int count;

                err = Send(s, query, strlen(query), 0, count, item);
                if (IsError(err))
                    result = kError_UserCancel; 
                if(count != (int)strlen(query))
                {
                    result = kError_IOError;
                }

                if(item->GetState() != kDownloadItemState_Downloading)
                    result = kError_UserCancel;

⌨️ 快捷键说明

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