123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872 |
- #include <string.h>
- #include <strsafe.h>
- #include <iostream>
- #include <cstdio>
- #include <QtCore/qglobal.h>
- #include <QWebEngineProfile>
- #include <QtWebEngineWidgets/QtWebEngineWidgets>
- #include <QWebEnginePage>
- #include <QWebEngineSettings>
- #include "api__wac_downloadManager.h"
- #include "wac_downloadManager.h"
- #include "wac_download_http_receiver_api.h"
- #include "..\wac_network\wac_network_http_receiver_api.h"
- #include "api/service/waservicefactory.h"
- #include "../nu/threadname.h"
- #include "../nu/AutoChar.h"
- #include "../nu/threadpool/timerhandle.hpp"
- #include "..\WAT\WAT.h"
- #include "..\Winamp\buildType.h"
- static const GUID internetConfigGroupGUID =
- {
- 0xc0a565dc, 0xcfe, 0x405a, { 0xa2, 0x7c, 0x46, 0x8b, 0xc, 0x8a, 0x3a, 0x5c }
- };
- #define DOWNLOAD_TIMEOUT_MS 60000 // 60 second timeout
- #define DOWNLOAD_SLEEP_MS 50
- #define DOWNLOAD_BUFFER_SIZE 1310720 // gives a maximum download rate of 25 mb/sec per file
- /**********************************************************************************
- **********************************************************************************/
- /**********************************************************************************
- * PUBLIC *
- **********************************************************************************/
- wa::Components::WAC_DownloadData::WAC_DownloadData( api_wac_download_manager_http_receiver *p_http, const char *p_url, int p_flags, ifc_downloadManagerCallback *p_callback )
- {
- _http = p_http;
- strcpy_s( this->_url, 1024, p_url );
- _flags = p_flags;
- _callback = p_callback;
- if ( _callback )
- _callback->AddRef();
- _hFile = INVALID_HANDLE_VALUE;
- _filepath[ 0 ] = 0;
- _fileext = 0;
- int download_method = ( api_downloadManager::DOWNLOADEX_MASK_DOWNLOADMETHOD & _flags );
- switch ( download_method )
- {
- case api_downloadManager::DOWNLOADEX_TEMPFILE:
- {
- wchar_t temppath[ MAX_PATH - 14 ] = { 0 }; // MAX_PATH-14 'cause MSDN said so
- GetTempPathW( MAX_PATH - 14, temppath );
- GetTempFileNameW( temppath, L"wdl", 0, _filepath );
- _hFile = CreateFileW( _filepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0 );
- }
- break;
- case api_downloadManager::DOWNLOADEX_CALLBACK:
- if ( _callback )
- _callback->GetLocation( _filepath, MAX_PATH );
- break;
- }
-
- _source[ 0 ] = 0;
- _title[ 0 ] = 0;
- if ( _flags & api_downloadManager::DOWNLOADEX_CALLBACK )
- {
- if ( _callback )
- {
- _callback->GetSource( _source, 1024 );
- _callback->GetTitle( _title, 1024 );
- }
- }
- _connectionStart = _lastDownloadTick = GetTickCount();
- _last_status = HTTP_RECEIVER_STATUS_ERROR;
- _pending = ( _flags & api_downloadManager::DOWNLOADEX_PENDING ) > 0;
- }
- wa::Components::WAC_DownloadData::~WAC_DownloadData()
- {
- ServiceRelease( _http, httpreceiverGUID2 );
- _http = NULL;
- if ( _fileext )
- delete _fileext;
- int download_method = ( api_downloadManager::DOWNLOADEX_MASK_DOWNLOADMETHOD & _flags );
- if ( download_method == api_downloadManager::DOWNLOADEX_TEMPFILE && _filepath[ 0 ] )
- DeleteFileW( _filepath );
- if ( _callback )
- _callback->Release();
- _callback = NULL;
- }
- void wa::Components::WAC_DownloadData::Retain()
- {
- this->_refCount.fetch_add( 1 );
- }
- void wa::Components::WAC_DownloadData::Release()
- {
- if ( this->_refCount.fetch_sub( 1 ) == 0 )
- delete this;
- }
- void wa::Components::WAC_DownloadData::Close( ifc_downloadManagerCallback **callbackCopy )
- {
- if ( _hFile != INVALID_HANDLE_VALUE )
- CloseHandle( _hFile );
- _hFile = INVALID_HANDLE_VALUE;
- if ( callbackCopy != NULL )
- {
- *callbackCopy = _callback;
- if ( _callback != NULL )
- _callback->AddRef();
- }
- else if ( _callback != NULL )
- {
- _callback->Release();
- _callback = NULL;
- }
- // don't want to close http here, because someone might still want to get the headers out of it
- }
- bool wa::Components::WAC_DownloadData::getExtention()
- {
- if ( _fileext && *_fileext )
- return _fileext;
- char l_header_name_content_type[] = "Content-Type";
- char *l_content_type = _http->getheader( l_header_name_content_type );
- if ( l_content_type && *l_content_type )
- {
- if ( _CONTENT_TYPES_EXTENSIONS.count( l_content_type ) == 1 )
- _fileext = _strdup( _CONTENT_TYPES_EXTENSIONS.find( l_content_type )->second.c_str() );
- }
- return _fileext;
- }
- /**********************************************************************************
- * PRIVATE *
- **********************************************************************************/
- /**********************************************************************************
- **********************************************************************************/
- /**********************************************************************************
- * PUBLIC *
- **********************************************************************************/
- wa::Components::WAC_DownloadManager::WAC_DownloadManager( QObject *parent ) : QNetworkAccessManager( parent )
- {
- this->setObjectName( "DownloadManagerService" );
- this->init();
- }
- wa::Components::WAC_DownloadManager::~WAC_DownloadManager()
- {
- disconnect( _connection_authentication_required );
- }
- DownloadToken wa::Components::WAC_DownloadManager::Download( const char *p_url, ifc_downloadManagerCallback *p_callback )
- {
- return DownloadEx( p_url, p_callback, api_downloadManager::DOWNLOADEX_TEMPFILE );
- }
- DownloadToken wa::Components::WAC_DownloadManager::DownloadEx( const char *p_url, ifc_downloadManagerCallback *p_callback, int p_flags )
- {
- return DownloadToken();
- }
- /**********************************************************************************
- * PRIVATE *
- **********************************************************************************/
- void wa::Components::WAC_DownloadManager::init()
- {
- QString l_winamp_user_agent = QString( "%1 Winamp/%2" ).arg( QWebEngineProfile::defaultProfile()->httpUserAgent(), STR_WINAMP_PRODUCTVER ).replace( ",", "." );
- QWebEngineProfile::defaultProfile()->setHttpUserAgent( l_winamp_user_agent );
- _connection_authentication_required = connect( this, &QNetworkAccessManager::authenticationRequired, this, &wa::Components::WAC_DownloadManager::on_s_authentication_required );
- }
- QNetworkReply *wa::Components::WAC_DownloadManager::createRequest( Operation p_operation, const QNetworkRequest &p_request, QIODevice *p_outgoing_data )
- {
- return QNetworkAccessManager::createRequest( p_operation, p_request, p_outgoing_data );
- }
- /**********************************************************************************
- * PRIVATE SLOTS *
- **********************************************************************************/
- void wa::Components::WAC_DownloadManager::on_s_authentication_required( QNetworkReply *p_reply, QAuthenticator *p_authenticator )
- {
- Q_UNUSED( p_reply );
- Q_UNUSED( p_authenticator );
- }
- /**********************************************************************************
- **********************************************************************************/
- DownloadData::DownloadData( api_httpreceiver *p_http, const char *p_url, int p_flags, ifc_downloadManagerCallback *p_callback )
- {
- flags = p_flags;
- http = p_http;
- callback = p_callback;
- if ( callback )
- callback->AddRef();
- hFile = INVALID_HANDLE_VALUE;
- filepath[ 0 ] = 0;
- fileext = 0;
- int download_method = ( api_downloadManager::DOWNLOADEX_MASK_DOWNLOADMETHOD & flags );
- switch ( download_method )
- {
- case api_downloadManager::DOWNLOADEX_TEMPFILE:
- {
- wchar_t temppath[ MAX_PATH - 14 ] = { 0 }; // MAX_PATH-14 'cause MSDN said so
- GetTempPathW( MAX_PATH - 14, temppath );
- GetTempFileNameW( temppath, L"wdl", 0, filepath );
- hFile = CreateFileW( filepath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0 );
- }
- break;
- case api_downloadManager::DOWNLOADEX_CALLBACK:
- if ( callback )
- callback->GetLocation( filepath, MAX_PATH );
- break;
- }
- strcpy_s( this->url, 1024, p_url );
- source[ 0 ] = 0;
- title[ 0 ] = 0;
- if ( flags & api_downloadManager::DOWNLOADEX_CALLBACK )
- {
- if ( callback )
- {
- callback->GetSource( source, 1024 );
- callback->GetTitle( title, 1024 );
- }
- }
- connectionStart = lastDownloadTick = GetTickCount();
- last_status = HTTPRECEIVER_STATUS_ERROR;
- pending = ( flags & api_downloadManager::DOWNLOADEX_PENDING ) > 0;
- }
- DownloadData::~DownloadData()
- {
- ServiceRelease( http, httpreceiverGUID );
- http = NULL;
- if ( fileext )
- delete fileext;
- int download_method = ( api_downloadManager::DOWNLOADEX_MASK_DOWNLOADMETHOD & flags );
- if ( download_method == api_downloadManager::DOWNLOADEX_TEMPFILE && filepath[ 0 ] )
- DeleteFileW( filepath );
- if ( callback )
- callback->Release();
- callback = NULL;
- }
- void DownloadData::Retain()
- {
- this->_refCount.fetch_add( 1 );
- }
- void DownloadData::Release()
- {
- if ( this->_refCount.fetch_sub( 1 ) == 0 )
- delete this;
- }
- void DownloadData::Close( ifc_downloadManagerCallback **callbackCopy )
- {
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
- hFile = INVALID_HANDLE_VALUE;
- if ( callbackCopy != NULL )
- {
- *callbackCopy = callback;
- if ( callback != NULL )
- callback->AddRef();
- }
- else if ( callback != NULL )
- {
- callback->Release();
- callback = NULL;
- }
- // don't want to close http here, because someone might still want to get the headers out of it
- }
- bool DownloadData::getExtention()
- {
- if ( fileext && *fileext )
- return fileext;
- char l_header_name_content_type[] = "Content-Type";
- char *l_content_type = http->getheader( l_header_name_content_type );
- if ( l_content_type && *l_content_type )
- {
- if ( _CONTENT_TYPES_EXTENSIONS.count( l_content_type ) == 1 )
- fileext = _strdup( _CONTENT_TYPES_EXTENSIONS.find( l_content_type )->second.c_str() );
- }
- return fileext;
- }
- /**********************************************************************************
- **********************************************************************************/
- /**********************************************************************************
- * PUBLIC *
- **********************************************************************************/
- DownloadManager::DownloadManager()
- {
- download_thread = NULL;
- killswitch = CreateEvent( NULL, TRUE, FALSE, NULL );
- InitializeCriticalSection( &downloadsCS );
- }
- void DownloadManager::Kill()
- {
- SetEvent( killswitch );
- if ( download_thread )
- {
- WaitForSingleObject( download_thread, 3000 );
- CloseHandle( download_thread );
- }
- DeleteCriticalSection( &downloadsCS );
- CloseHandle( killswitch );
- }
- static void SetUserAgent( api_httpreceiver *p_http )
- {
- char agent[ 256 ] = { 0 };
- StringCchPrintfA( agent, 256, "User-Agent: %S/%S", WASABI_API_APP->main_getAppName(), WASABI_API_APP->main_getVersionNumString() );
- p_http->addheader( agent );
- //QString l_winamp_user_agent = QString( "User-Agent: %1 Winamp/%2" ).arg( QWebEngineProfile::defaultProfile()->httpUserAgent(), STR_WINAMP_PRODUCTVER ).replace( ",", "." );
- //http->addheader( l_winamp_user_agent.toStdString().c_str() );
- }
- DownloadToken DownloadManager::Download( const char *url, ifc_downloadManagerCallback *callback )
- {
- return DownloadEx( url, callback, api_downloadManager::DOWNLOADEX_TEMPFILE );
- }
- DownloadToken DownloadManager::DownloadEx( const char *url, ifc_downloadManagerCallback *callback, int flags )
- {
- if ( InitDownloadThread() )
- {
- api_httpreceiver *http = NULL;
- ServiceBuild( http, httpreceiverGUID );
- if ( http )
- {
- DownloadData *downloadData = new DownloadData( http, url, flags, callback );
- int use_proxy = 1;
- bool proxy80 = AGAVE_API_CONFIG->GetBool( internetConfigGroupGUID, L"proxy80", false );
- if ( proxy80 && strstr( url, ":" ) && ( !strstr( url, ":80/" ) && strstr( url, ":80" ) != ( url + strlen( url ) - 3 ) ) )
- use_proxy = 0;
- const wchar_t *proxy = use_proxy ? AGAVE_API_CONFIG->GetString( internetConfigGroupGUID, L"proxy", 0 ) : 0;
- http->open( API_DNS_AUTODNS, DOWNLOAD_BUFFER_SIZE, ( proxy && proxy[ 0 ] ) ? (const char *)AutoChar( proxy ) : NULL );
- SetUserAgent( http );
- if ( callback )
- callback->OnInit( downloadData );
- if ( downloadData->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_status : status_callbacks )
- l_status->OnInit( downloadData );
- }
- //only call http->connect when it is not pending download request
- if ( !( flags & DOWNLOADEX_PENDING ) )
- http->connect( url, 1 );
- //http->run(); // let's get this party started
- EnterCriticalSection( &downloadsCS );
- downloads.push_back( downloadData );
- LeaveCriticalSection( &downloadsCS );
- return downloadData;
- }
- }
- return 0;
- }
- void DownloadManager::ResumePendingDownload( DownloadToken p_token )
- {
- if ( !p_token )
- return;
- DownloadData *data = (DownloadData *)p_token;
- if ( data->pending )
- {
- data->pending = false;
- data->connectionStart = data->lastDownloadTick = GetTickCount();
- data->http->connect( data->url );
- }
- }
- void DownloadManager::CancelDownload( DownloadToken p_token )
- {
- if ( !p_token )
- return;
- DownloadData *data = (DownloadData *)p_token;
- EnterCriticalSection( &downloadsCS );
- if ( downloads.end() != std::find( downloads.begin(), downloads.end(), data ) )
- {
- ifc_downloadManagerCallback *callback;
- data->Close( &callback );
- //downloads.eraseObject(p_data);
- auto it = std::find( downloads.begin(), downloads.end(), data );
- if ( it != downloads.end() )
- {
- downloads.erase( it );
- }
- LeaveCriticalSection( &downloadsCS );
- if ( callback )
- {
- callback->OnCancel( p_token );
- if ( data->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_status : status_callbacks )
- l_status->OnCancel( p_token );
- }
- callback->Release();
- }
- data->Release();
- }
- else
- LeaveCriticalSection( &downloadsCS );
- }
- void DownloadManager::RetainDownload( DownloadToken p_token )
- {
- if ( !p_token )
- return;
- DownloadData *data = (DownloadData *)p_token;
- if ( data )
- data->Retain();
- }
- void DownloadManager::ReleaseDownload( DownloadToken p_token )
- {
- if ( !p_token )
- return;
- DownloadData *data = (DownloadData *)p_token;
- if ( data )
- data->Release();
- }
- void DownloadManager::RegisterStatusCallback( ifc_downloadManagerCallback *callback )
- {
- EnterCriticalSection( &downloadsCS );
- status_callbacks.push_back( callback );
- LeaveCriticalSection( &downloadsCS );
- }
- void DownloadManager::UnregisterStatusCallback( ifc_downloadManagerCallback *callback )
- {
- EnterCriticalSection( &downloadsCS );
- auto it = std::find( status_callbacks.begin(), status_callbacks.end(), callback );
- if ( it != status_callbacks.end() )
- status_callbacks.erase( it );
- LeaveCriticalSection( &downloadsCS );
- }
- bool DownloadManager::IsPending( DownloadToken token )
- {
- DownloadData *data = (DownloadData *)token;
- if ( data )
- return data->pending;
- else
- return FALSE;
- }
- /**********************************************************************************
- * PRIVATE *
- **********************************************************************************/
- bool DownloadManager::DownloadThreadTick()
- {
- unsigned int i = 0;
- char *downloadBuffer = (char *)malloc( DOWNLOAD_BUFFER_SIZE );
- while ( WaitForSingleObject( killswitch, 0 ) != WAIT_OBJECT_0 )
- {
- EnterCriticalSection( &downloadsCS );
- if ( downloads.empty() )
- {
- // TODO: might be nice to dynamically increase the sleep time if this happens
- // (maybe to INFINITE and have Download() wake us?)
- LeaveCriticalSection( &downloadsCS );
- free( downloadBuffer );
- return true;
- }
- if ( i >= downloads.size() )
- {
- LeaveCriticalSection( &downloadsCS );
- free( downloadBuffer );
- return true;
- }
- DownloadData *thisDownload = downloads[ i ];
- if ( thisDownload->pending )
- {
- LeaveCriticalSection( &downloadsCS );
- }
- else
- {
- thisDownload->Retain();
- LeaveCriticalSection( &downloadsCS );
- INT tick = Tick( thisDownload, downloadBuffer, DOWNLOAD_BUFFER_SIZE );
- switch ( tick )
- {
- case TICK_NODATA:
- // do nothing
- break;
- case TICK_CONNECTING:
- break;
- case TICK_CONNECTED:
- if ( thisDownload->callback )
- thisDownload->callback->OnConnect( thisDownload );
- if ( thisDownload->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_status : status_callbacks )
- l_status->OnConnect( thisDownload );
- }
- break;
- case TICK_SUCCESS:
- if ( thisDownload->callback )
- thisDownload->callback->OnTick( thisDownload );
- if ( thisDownload->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_status : status_callbacks )
- l_status->OnTick( thisDownload );
- }
- // TODO: send out update l_callback
- break;
- case TICK_FINISHED:
- case TICK_FAILURE:
- case TICK_TIMEOUT:
- case TICK_CANT_CONNECT:
- case TICK_WRITE_ERROR:
- FinishDownload( thisDownload, tick );
- break;
- }
- thisDownload->Release();
- }
- i++;
- }
- free( downloadBuffer );
- return false; // we only get here when killswitch is set
- }
- int DownloadManager::DownloadTickThreadPoolFunc( HANDLE handle, void *user_data, intptr_t id )
- {
- DownloadManager *dlmgr = (DownloadManager *)user_data;
- if ( dlmgr->DownloadThreadTick() )
- {
- TimerHandle t( handle );
- t.Wait( DOWNLOAD_SLEEP_MS );
- }
- else
- {
- WASABI_API_THREADPOOL->RemoveHandle( 0, handle );
- SetEvent( dlmgr->download_thread );
- }
- return 0;
- }
- bool DownloadManager::InitDownloadThread()
- {
- if ( download_thread == NULL )
- {
- download_thread = CreateEvent( 0, FALSE, FALSE, 0 );
- TimerHandle t;
- WASABI_API_THREADPOOL->AddHandle( 0, t, DownloadTickThreadPoolFunc, this, 0, api_threadpool::FLAG_LONG_EXECUTION );
- t.Wait( DOWNLOAD_SLEEP_MS );
- }
- return ( download_thread != NULL );
- }
- void DownloadManager::FinishDownload( DownloadData *p_data, int code )
- {
- if ( p_data == NULL )
- return;
- ifc_downloadManagerCallback *l_callback = NULL;
- EnterCriticalSection( &downloadsCS );
- p_data->Close( &l_callback );
- LeaveCriticalSection( &downloadsCS );
- if ( l_callback != NULL )
- {
- if ( code == TICK_FINISHED )
- {
- l_callback->OnFinish( p_data );
- if ( p_data->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_data : status_callbacks )
- l_data->OnFinish( p_data );
- }
- }
- else
- {
- l_callback->OnError( p_data, code );
- if ( p_data->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_data : status_callbacks )
- l_data->OnError( p_data, code );
- }
- }
- l_callback->Release();
- }
- EnterCriticalSection( &downloadsCS );
- auto it = std::find( downloads.begin(), downloads.end(), p_data );
- if ( it != downloads.end() )
- downloads.erase( it );
- LeaveCriticalSection( &downloadsCS );
- p_data->Release();
- }
- int DownloadManager::Tick( DownloadData *thisDownload, void *buffer, int bufferSize )
- {
- if ( !thisDownload )
- return api_downloadManager::TICK_FAILURE;
- int state = thisDownload->http->run();
- if ( state == HTTPRECEIVER_RUN_ERROR || thisDownload == NULL )
- return api_downloadManager::TICK_FAILURE;
- if ( !thisDownload->fileext )
- thisDownload->getExtention();
- int downloaded = thisDownload->http->get_bytes( buffer, bufferSize );
- if ( downloaded )
- {
- switch ( thisDownload->flags & DOWNLOADEX_MASK_DOWNLOADMETHOD )
- {
- case api_downloadManager::DOWNLOADEX_BUFFER:
- {
- thisDownload->buffer.reserve( thisDownload->http->content_length() );
- thisDownload->buffer.add( buffer, downloaded );
- }
- break;
- case api_downloadManager::DOWNLOADEX_TEMPFILE:
- {
- DWORD written = 0;
- WriteFile( thisDownload->hFile, buffer, downloaded, &written, NULL );
- if ( written != downloaded )
- return api_downloadManager::TICK_WRITE_ERROR;
- }
- break;
- case api_downloadManager::DOWNLOADEX_CALLBACK:
- {
- if ( thisDownload->flags & api_downloadManager::DOWNLOADEX_UI )
- {
- for ( ifc_downloadManagerCallback *l_status : status_callbacks )
- l_status->OnData( thisDownload, buffer, downloaded );
- }
- if ( thisDownload->callback )
- thisDownload->callback->OnData( thisDownload, buffer, downloaded );
- }
- }
- thisDownload->lastDownloadTick = GetTickCount();
- thisDownload->bytesDownloaded += downloaded;
- return api_downloadManager::TICK_SUCCESS;
- }
- else // nothing in the buffer
- {
- if ( state == HTTPRECEIVER_RUN_CONNECTION_CLOSED ) // see if the connection is closed
- {
- return api_downloadManager::TICK_FINISHED; // yay we're done
- }
- if ( GetTickCount() - thisDownload->lastDownloadTick > DOWNLOAD_TIMEOUT_MS ) // check for timeout
- return api_downloadManager::TICK_TIMEOUT;
- switch ( thisDownload->http->get_status() )
- {
- case HTTPRECEIVER_STATUS_CONNECTING:
- if ( thisDownload->last_status != HTTPRECEIVER_STATUS_CONNECTING )
- {
- thisDownload->last_status = HTTPRECEIVER_STATUS_CONNECTING;
- return api_downloadManager::TICK_CONNECTING;
- }
- else
- {
- return api_downloadManager::TICK_NODATA;
- }
- case HTTPRECEIVER_STATUS_READING_HEADERS:
- if ( thisDownload->last_status != HTTPRECEIVER_STATUS_READING_HEADERS )
- {
- thisDownload->last_status = HTTPRECEIVER_STATUS_READING_HEADERS;
- return api_downloadManager::TICK_CONNECTED;
- }
- else
- {
- return api_downloadManager::TICK_NODATA;
- }
- }
- if ( !thisDownload->replyCode )
- thisDownload->replyCode = thisDownload->http->getreplycode();
- switch ( thisDownload->replyCode )
- {
- case 0:
- case 100:
- case 200:
- case 201:
- case 202:
- case 203:
- case 204:
- case 205:
- case 206:
- return api_downloadManager::TICK_NODATA;
- default:
- return api_downloadManager::TICK_CANT_CONNECT;
- }
- }
- }
- #define CBCLASS DownloadManager
- START_DISPATCH;
- CB( API_DOWNLOADMANAGER_DOWNLOAD, Download )
- CB( API_DOWNLOADMANAGER_DOWNLOADEX, DownloadEx )
- CB( API_DOWNLOADMANAGER_GETRECEIVER, GetReceiver )
- CB( API_DOWNLOADMANAGER_GETLOCATION, GetLocation )
- VCB( API_DOWNLOADMANAGER_SETLOCATION, SetLocation )
- CB( API_DOWNLOADMANAGER_GETEXTENTION, GetExtention )
- CB( API_DOWNLOADMANAGER_GETURL, GetUrl )
- CB( API_DOWNLOADMANAGER_GETBYTESDOWNLOADED, GetBytesDownloaded );
- CB( API_DOWNLOADMANAGER_GETBUFFER, GetBuffer );
- VCB( API_DOWNLOADMANAGER_RESUMEPENDINGDOWNLOAD, ResumePendingDownload );
- VCB( API_DOWNLOADMANAGER_CANCELDOWNLOAD, CancelDownload );
- VCB( API_DOWNLOADMANAGER_RETAINDOWNLOAD, RetainDownload );
- VCB( API_DOWNLOADMANAGER_RELEASEDOWNLOAD, ReleaseDownload );
- VCB( API_DOWNLOADMANAGER_REGISTERSTATUSCALLBACK, RegisterStatusCallback );
- VCB( API_DOWNLOADMANAGER_UNREGISTERSTATUSCALLBACK, UnregisterStatusCallback );
- CB( API_DOWNLOADMANAGER_GETSOURCE, GetSource );
- CB( API_DOWNLOADMANAGER_GETTITLE, GetTitle );
- CB( API_DOWNLOADMANAGER_ISPENDING, IsPending );
- END_DISPATCH;
- #undef CBCLASS
|