📄 downloadmanager.cpp
字号:
delete [] query;
}
}
// receive response
if(IsntError(result))
{
uint32 bufferSize = 2048;
char* buffer = NULL;
int count;
uint32 total = 0;
buffer = (char*)malloc(bufferSize);
result = kError_OutOfMemory;
if(buffer)
{
Error err;
result = kError_NoErr;
do
{
if(total >= bufferSize - 1)
{
bufferSize *= 2;
buffer = (char*) realloc(buffer, bufferSize);
if(!buffer)
{
result = kError_OutOfMemory;
break;
}
}
err = Recv(s, buffer + total, bufferSize - total - 1, 0, count, item);
if (IsError(err))
result = kError_UserCancel;
if(count > 0)
total += count;
else
{
result = kError_IOError;
}
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
}while(IsntError(result) && !IsHTTPHeaderComplete(buffer, total));
}
// parse header
if(IsntError(result))
{
uint32 returnCode = atoi(buffer+9);
buffer[total] = 0x00;
//cout << buffer << endl;
//cout << returnCode << endl;
switch(buffer[9])
{
// 1xx: Informational - Request received, continuing process
case '1':
{
// not sure what to do here... continue receiving???
}
// 2xx: Success - The action was successfully received,
// understood, and accepted
case '2':
{
result = kError_UnknownErr;
int32 fileSize = GetContentLengthFromHeader(buffer);
//cout << destPath << endl;
int openFlags = O_BINARY|O_CREAT|O_RDWR|O_APPEND;
if(returnCode != 206) // server didn't ok partial
{
string mTime;
item->SetBytesReceived(0);
openFlags |= O_TRUNC;
GetContentTimeFromHeader(buffer, mTime);
item->SetMTime(mTime.c_str());
if(fileSize > 0)
item->SetTotalBytes(fileSize);
}
int fd = open(destPath, openFlags, S_IREAD | S_IWRITE);
if(fd >= 0)
{
Error err;
lseek(fd, 0, SEEK_END);
result = kError_NoErr;
int wcount = 0;
char* cp = strstr(buffer, "\n\n");
if(cp)
cp += 2;
else
{
cp = strstr(buffer, "\r\n\r\n");
if(cp)
cp += 4;
}
if(cp)
{
if(cp - buffer < (int)total)
{
wcount = write(fd, cp, total - (cp - buffer));
item->SetBytesReceived(total - (cp - buffer) + item->GetBytesReceived());
SendProgressMessage(item);
}
}
do
{
err = Recv(s, buffer, bufferSize, 0, count, item);
if (IsError(err))
result = kError_UserCancel;
else
if(count > 0)
{
wcount = write(fd, buffer, count);
item->SetBytesReceived(count + item->GetBytesReceived());
SendProgressMessage(item);
}
if(count < 0)
result = kError_IOError;
if(wcount < 0)
result = kError_WriteFile;
if(item->GetState() != kDownloadItemState_Downloading)
result = kError_UserCancel;
}while(count > 0 && IsntError(result) &&
m_runDownloadThread && wcount >= 0 &&
(item->GetTotalBytes() > item->GetBytesReceived()));
close(fd);
}
else
{
//*m_debug << "error opening file: " << endl;
switch(errno)
{
case EEXIST:
result = kError_FileExists;
break;
case EACCES:
result = kError_FileNoAccess;
break;
case ENOENT:
result = kError_FileNotFound;
break;
case EMFILE:
result = kError_FileNoHandles;
break;
case EINVAL:
result = kError_FileInvalidArg;
break;
}
}
break;
}
// 3xx: Redirection - Further action must be taken in order to
// complete the request
case '3':
{
char* cp = strstr(buffer, "Location:");
//int32 length;
if(cp)
{
cp += 9;
if(*cp == 0x20)
cp++;
char *end;
for(end = cp; end < buffer + total; end++)
if(*end=='\r' || *end == '\n') break;
*end = 0x00;
if (305 == returnCode) // proxy
{
char* proxy = new char[strlen(cp) +
strlen(item->SourceURL().c_str()) + 1];
sprintf(proxy, "%s%s", cp, item->SourceURL().c_str());
item->SetSourceURL(proxy);
delete [] proxy;
}
else // redirect of some type
{
item->SetSourceURL(cp);
}
result = Download(item);
}
break;
}
// 4xx: Client Error - The request contains bad syntax or cannot
// be fulfilled
case '4':
{
//*m_debug << "HTTP Error: " << returnCode << endl;
switch(returnCode)
{
case 400:
result = kError_BadHTTPRequest;
break;
case 401:
result = kError_AccessNotAuthorized;
break;
case 403:
result = kError_DownloadDenied;
break;
case 404:
result = kError_HTTPFileNotFound;
break;
case 416:
// try to grab the whole thing...
item->SetBytesReceived(0);
result = Download(item);
break;
default:
result = kError_UnknownErr;
break;
}
break;
}
// 5xx: Server Error - The server failed to fulfill an apparently
// valid request
case '5':
{
result = kError_UnknownServerError;
break;
}
}
}
// cleanup
if(buffer)
free(buffer);
}
// cleanup
if(s > 0)
closesocket(s);
if(destPath)
delete [] destPath;
}
return result;
}
void DownloadManager::CleanUpDownload(DownloadItem* item)
{
//cout << "Cleaning item: " << item->SourceURL() << endl;
char path[_MAX_PATH];
uint32 length = sizeof(path);
m_context->prefs->GetPrefString(kSaveMusicDirPref, path, &length);
strcat(path, DIR_MARKER_STR);
strcat(path, item->DestinationFile().c_str());
remove(path);
item->SetBytesReceived(0);
}
Error DownloadManager::SubmitToDatabase(DownloadItem* item)
{
Error result = kError_InvalidParam;
assert(item);
if(item)
{
//cout << "Submitting item: " << item->SourceURL() << endl;
char path[_MAX_PATH];
uint32 length = sizeof(path);
m_context->prefs->GetPrefString(kSaveMusicDirPref, path, &length);
strcat(path, DIR_MARKER_STR);
strcat(path, item->DestinationFile().c_str());
uint32 urlLength = strlen(path) + 10;
char *url = new char[urlLength];
if (IsntError(FilePathToURL(path, url, &urlLength)))
{
PlaylistItem *newtrack;
if (item->IsNormalDownload())
newtrack = new PlaylistItem(url);
else
newtrack = new PlaylistItem(url, &(item->GetMetaData()));
m_context->plm->RetrieveMetaDataNow(newtrack);
MetaData tempdata = (MetaData)(newtrack->GetMetaData());
m_context->catalog->WriteMetaDataToDatabase(url, tempdata);
m_context->catalog->AddSong(url);
delete newtrack;
}
delete [] url;
}
return result;
}
void DownloadManager::PauseDownloads(void)
{
m_downloadsPaused = true;
}
void DownloadManager::ResumeDownloads(void)
{
m_downloadsPaused = false;
m_queueSemaphore.Signal();
}
bool DownloadManager::IsPaused(void)
{
return m_downloadsPaused;
}
void DownloadManager::DownloadThreadFunction()
{
DownloadItem* item;
Error result;
m_quitMutex.Acquire();
while(m_runDownloadThread)
{
if (m_downloadsPaused)
{
m_queueSemaphore.Wait();
continue;
}
item = GetNextQueuedItem();
if(item)
{
item->SetState(kDownloadItemState_Downloading);
SendStateChangedMessage(item);
result = Download(item);
if(IsntError(result))
{
item->SetState(kDownloadItemState_Done);
result = SubmitToDatabase(item);
}
else if(result == kError_UserCancel)
{
if(item->GetState() == kDownloadItemState_Cancelled)
{
CleanUpDownload(item);
}
}
else
{
item->SetState(kDownloadItemState_Error);
if (result != kError_IOError)
CleanUpDownload(item);
}
item->SetDownloadError(result);
SendStateChangedMessage(item);
}
else
{
m_queueSemaphore.Wait();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -