2010-08-31 03:50:41 +02:00
/******************************************************************************
2010-09-01 10:52:02 +02:00
libprozilla - a download accelerator library
Copyright ( C ) 2001 Kalum Somaratna
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
2010-08-31 03:50:41 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Download routines. */
2010-09-01 10:52:02 +02:00
/* $Id$ */
2010-08-31 03:50:41 +02:00
# include "common.h"
# include "download.h"
# include "ftp-retr.h"
# include "http-retr.h"
# include "logfile.h"
# include "debug.h"
# include "ftpsearch.h"
/******************************************************************************
2010-09-01 10:52:02 +02:00
Initialize the download .
2010-08-31 03:50:41 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
download_t * proz_download_init ( urlinfo * u )
{
/* pthread_mutexattr_t attr; */
download_t * download = kmalloc ( sizeof ( download_t ) ) ;
/* attr.__mutexkind = PTHREAD_MUTEX_RECURSIVE_NP; */
memset ( download , 0 , sizeof ( download_t ) ) ;
/*FIXME pthread_mutex_init(&download->status_change_mutex, &attr); */
pthread_mutex_init ( & download - > status_change_mutex , NULL ) ;
pthread_mutex_init ( & download - > access_mutex , NULL ) ;
memcpy ( & download - > u , u , sizeof ( urlinfo ) ) ;
download - > dl_dir = kmalloc ( PATH_MAX ) ;
download - > output_dir = kmalloc ( PATH_MAX ) ;
download - > log_dir = kmalloc ( PATH_MAX ) ;
strcpy ( download - > dl_dir , libprozrtinfo . dl_dir ) ;
strcpy ( download - > output_dir , libprozrtinfo . output_dir ) ;
strcpy ( download - > log_dir , libprozrtinfo . log_dir ) ;
download - > resume_mode = FALSE ;
download - > max_simul_connections = 0 ;
download - > max_allowed_bps = libprozrtinfo . max_bps_per_dl ;
2010-09-01 10:52:02 +02:00
download - > file_build_msg = ( char * ) kmalloc ( MAX_MSG_SIZE + 1 ) ;
2010-08-31 03:50:41 +02:00
download - > using_ftpsearch = FALSE ;
return download ;
}
/******************************************************************************
2010-09-01 10:52:02 +02:00
This will setup a download based on the connection info , and will attempt
to setup req_connections , but it might not be possible if we dont know the
file size , returns the number of connections allocated .
2010-08-31 03:50:41 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int proz_download_setup_connections_no_ftpsearch ( download_t * download ,
2010-09-01 10:52:02 +02:00
connection_t * connection ,
int req_connections )
2010-08-31 03:50:41 +02:00
{
int num_connections , i ;
off_t bytes_per_connection ;
off_t bytes_left ;
FILE * fp ;
char * out_file ;
struct stat stat_buf ;
download - > main_file_size = connection - > main_file_size ;
download - > resume_support = connection - > resume_support ;
if ( download - > main_file_size = = - 1 )
{
num_connections = 1 ;
bytes_per_connection = - 1 ;
bytes_left = - 1 ;
2010-09-01 10:52:02 +02:00
}
else
{
if ( connection - > resume_support = = FALSE )
num_connections = 1 ;
else
num_connections = req_connections ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
bytes_per_connection = connection - > main_file_size / num_connections ;
bytes_left = connection - > main_file_size % num_connections ;
}
2010-08-31 03:50:41 +02:00
download - > pconnections = kmalloc ( sizeof ( connection_t * ) * num_connections ) ;
download - > num_connections = num_connections ;
2010-09-01 10:52:02 +02:00
out_file = kmalloc ( PATH_MAX ) ;
2010-08-31 03:50:41 +02:00
snprintf ( out_file , PATH_MAX , " %s/%s.prozilla " ,
2010-09-01 10:52:02 +02:00
download - > dl_dir , connection - > u . file ) ;
proz_debug ( " out file %s " , out_file ) ;
2010-08-31 03:50:41 +02:00
//First see if the file exists then we dont create a new one else we do
if ( stat ( out_file , & stat_buf ) = = - 1 )
{
2010-09-01 10:52:02 +02:00
proz_debug ( " stat failed " ) ;
2010-08-31 03:50:41 +02:00
/* the call failed */
2010-09-01 10:52:02 +02:00
/* if the error is due to the file not been present then there is no
need to do anything . . just continue , otherwise return error ( - 1 )
*/
2010-08-31 03:50:41 +02:00
if ( errno = = ENOENT )
2010-09-01 10:52:02 +02:00
{
proz_debug ( " file doesnt exist " ) ;
//File not exists so create it
if ( !
( fp =
fopen ( out_file , " w+ " ) ) )
{
download_show_message ( download ,
_
( " Unable to open file %s: %s! " ) ,
out_file , strerror ( errno ) ) ;
proz_debug ( " Unable to open file %s: %s! " ,
out_file , strerror ( errno ) ) ;
return - 1 ;
}
proz_debug ( " created file " ) ;
}
2010-08-31 03:50:41 +02:00
else
2010-09-01 10:52:02 +02:00
{
proz_debug ( " something else happened %d " , errno ) ;
return - 1 ;
}
2010-08-31 03:50:41 +02:00
}
else
{
2010-09-01 10:52:02 +02:00
proz_debug ( " stat success " ) ;
2010-08-31 03:50:41 +02:00
//TODO: File exists : if it doesnt match file size warna boput it...
if ( !
2010-09-01 10:52:02 +02:00
( fp =
fopen ( out_file , " r+ " ) ) )
{
download_show_message ( download ,
_
( " Unable to open file %s: %s! " ) ,
out_file , strerror ( errno ) ) ;
proz_debug ( " Unable to open file %s: %s! " ,
out_file , strerror ( errno ) ) ;
return - 1 ;
}
2010-08-31 03:50:41 +02:00
}
//TRY setting the offset;
if ( download - > main_file_size ! = - 1 )
{
2010-09-01 10:52:02 +02:00
if ( fseeko ( fp , download - > main_file_size , SEEK_SET ) ! = 0 )
{
proz_debug ( " fseek failed " ) ;
return - 1 ;
}
2010-08-31 03:50:41 +02:00
}
/*Make sure all writes go directly to the file */
2010-09-01 10:52:02 +02:00
setvbuf ( fp , NULL , _IONBF , 0 ) ;
2010-08-31 03:50:41 +02:00
for ( i = 0 ; i < num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
download - > pconnections [ i ] = proz_connection_init ( & download - > u ,
& download - > status_change_mutex ) ;
2010-08-31 03:50:41 +02:00
/*Copy somethings we need from the original connection */
download - > resume_support = download - > pconnections [ i ] - > resume_support =
2010-09-01 10:52:02 +02:00
connection - > resume_support ;
2010-08-31 03:50:41 +02:00
memcpy ( & download - > pconnections [ i ] - > hs , & connection - > hs ,
2010-09-01 10:52:02 +02:00
sizeof ( http_stat_t ) ) ;
2010-08-31 03:50:41 +02:00
download - > pconnections [ i ] - > localfile = kmalloc ( PATH_MAX ) ;
strcpy ( out_file , download - > pconnections [ i ] - > localfile ) ;
2010-09-01 10:52:02 +02:00
download - > pconnections [ i ] - > fp = fp ;
2010-08-31 03:50:41 +02:00
download - > pconnections [ i ] - > retry = TRUE ;
if ( connection - > main_file_size = = - 1 )
2010-09-01 10:52:02 +02:00
{
download - > pconnections [ i ] - > main_file_size = - 1 ;
download - > pconnections [ i ] - > remote_startpos = 0 ;
download - > pconnections [ i ] - > orig_remote_startpos = 0 ;
download - > pconnections [ i ] - > remote_endpos = - 1 ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
download - > pconnections [ i ] - > local_startpos = 0 ;
}
else
{
download - > pconnections [ i ] - > main_file_size = connection - > main_file_size ;
download - > pconnections [ i ] - > orig_remote_startpos = download - > pconnections [ i ] - > remote_startpos = i * bytes_per_connection ;
download - > pconnections [ i ] - > remote_endpos =
i * bytes_per_connection + bytes_per_connection ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
//Changing things here.....
download - > pconnections [ i ] - > local_startpos = download - > pconnections [ i ] - > remote_startpos ;
}
2010-08-31 03:50:41 +02:00
/*Set the connections message to be download->msg_proc calback */
proz_connection_set_msg_proc ( download - > pconnections [ i ] ,
2010-09-01 10:52:02 +02:00
download - > msg_proc , download - > cb_data ) ;
2010-08-31 03:50:41 +02:00
}
/* Add the remaining bytes to the last connection */
download - > pconnections [ - - i ] - > remote_endpos + = bytes_left ;
download - > using_ftpsearch = FALSE ;
2010-09-01 10:52:02 +02:00
/*NOTE: Should we check for previously started downloads here and adjust
the local_startpos , accordingly or check for resumes later in another function
which is called after this ?
*/
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
proz_debug ( " return num_connections %d " , num_connections ) ;
2010-08-31 03:50:41 +02:00
return num_connections ;
}
/* This will for each connection setup the local_startpos and file write mode if any prior download exists returns 1 on success, and -1 on a error.*/
int proz_download_load_resume_info ( download_t * download )
{
int i ;
int ret = 1 ;
logfile lf ;
2010-09-01 10:52:02 +02:00
if ( proz_log_read_logfile ( & lf , download , TRUE ) = = 1 )
proz_debug ( " sucessfully loaded resume info " ) ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
for ( i = 0 ; i < download - > num_connections ; i + + )
{
if ( download - > pconnections [ i ] - > remote_endpos - download - > pconnections [ i ] - > remote_startpos = = download - > pconnections [ i ] - > remote_bytes_received )
{
connection_change_status ( download - > pconnections [ i ] , COMPLETED ) ;
//This should fix the error we received when resuming when the
//average rate was too high.
download - > pconnections [ i ] - > remote_startpos + = download - > pconnections [ i ] - > remote_bytes_received ;
continue ;
}
download - > pconnections [ i ] - > remote_startpos + = download - > pconnections [ i ] - > remote_bytes_received ;
}
2010-08-31 03:50:41 +02:00
download - > resume_mode = TRUE ;
return ret ;
}
2010-09-01 10:52:02 +02:00
/* This will create the threads and start the downloads,
2010-08-31 03:50:41 +02:00
if resume is true it will load the resume info too if the download supports it
2010-09-01 10:52:02 +02:00
*/
2010-08-31 03:50:41 +02:00
void proz_download_start_downloads ( download_t * download ,
2010-09-01 10:52:02 +02:00
boolean resume_mode )
2010-08-31 03:50:41 +02:00
{
int i ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
if ( resume_mode )
2010-09-01 10:52:02 +02:00
{
/*Does this download suport resume? */
if ( download - > resume_support = = TRUE )
proz_download_load_resume_info ( download ) ;
}
else
{
/*Create the log file */
if ( log_create_logfile
( download - > num_connections , download - > main_file_size ,
download - > u . url , download ) ! = 1 )
{
download_show_message ( download ,
_ ( " Warning! Unable to create logfile! " ) ) ;
}
}
2010-08-31 03:50:41 +02:00
/* Allocate number of threads */
download - > threads =
2010-09-01 10:52:02 +02:00
( pthread_t * ) kmalloc ( sizeof ( pthread_t ) * download - > num_connections ) ;
2010-08-31 03:50:41 +02:00
/*Create them */
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
switch ( download - > pconnections [ i ] - > u . proto )
{
case URLHTTP :
/* http_loop(&download->connections[i]); */
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & http_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
break ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
case URLFTP :
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
/* ftp_loop(&download->connections[i]); */
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
break ;
default :
proz_die ( _ ( " Error: Unsupported Protocol was specified " ) ) ;
}
2010-08-31 03:50:41 +02:00
}
download_show_message ( download , _ ( " All threads created " ) ) ;
}
void proz_download_stop_downloads ( download_t * download )
{
int i ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
/*Stop the threads */
for ( i = 0 ; i < download - > num_connections ; i + + )
2010-09-01 10:52:02 +02:00
{
pthread_cancel ( download - > threads [ i ] ) ;
pthread_join ( download - > threads [ i ] , NULL ) ;
}
2010-08-31 03:50:41 +02:00
}
/* returns one of DLINPROGRESS, DLERR, DLDONE, DLREMOTEFATAL, DLLOCALFATAL*/
uerr_t proz_download_handle_threads ( download_t * download )
{
//Create logfile everytime this is callaed
2010-09-01 10:52:02 +02:00
log_create_logfile ( download - > num_connections , download - > main_file_size , download - > u . url , download ) ;
2010-08-31 03:50:41 +02:00
if ( download - > using_ftpsearch = = TRUE )
return download_handle_threads_ftpsearch ( download ) ;
else
return download_handle_threads_no_ftpsearch ( download ) ;
}
/* returns one of DLINPROGRESS, DLERR, DLDONE, DLREMOTEFATAL, DLLOCALFATAL*/
uerr_t download_handle_threads_no_ftpsearch ( download_t * download )
{
int i ;
for ( i = 0 ; i < download - > num_connections ; i + + )
{
/*Set the DL start time if it is not done so */
pthread_mutex_lock ( download - > pconnections [ i ] - > status_change_mutex ) ;
if ( download - > pconnections [ i ] - > status = = DOWNLOADING
2010-09-01 10:52:02 +02:00
& & download - > start_time . tv_sec = = 0
& & download - > start_time . tv_usec = = 0 )
{
gettimeofday ( & download - > start_time , NULL ) ;
}
2010-08-31 03:50:41 +02:00
pthread_mutex_unlock ( download - > pconnections [ i ] - > status_change_mutex ) ;
}
/*If all the connections are completed then end them, and return complete */
if ( ( proz_download_all_dls_status ( download , COMPLETED ) ) = = TRUE )
{
char * out_filename ;
char * orig_filename ;
download_show_message ( download ,
2010-09-01 10:52:02 +02:00
" All the conenctions have retreived the file "
" ..waiting for them to end " ) ;
2010-08-31 03:50:41 +02:00
proz_download_wait_till_all_end ( download ) ;
download_show_message ( download , " All the threads have being ended. " ) ;
/*Close and rename file to original */
// flockfile(download->pconnections[0]->fp);
fclose ( download - > pconnections [ 0 ] - > fp ) ;
// funlockfile(download->pconnections[0]->fp);
2010-09-01 10:52:02 +02:00
out_filename = kmalloc ( PATH_MAX ) ;
orig_filename = kmalloc ( PATH_MAX ) ;
2010-08-31 03:50:41 +02:00
snprintf ( orig_filename , PATH_MAX , " %s/%s " ,
2010-09-01 10:52:02 +02:00
download - > dl_dir , download - > pconnections [ 0 ] - > u . file ) ;
2010-08-31 03:50:41 +02:00
snprintf ( out_filename , PATH_MAX , " %s/%s.prozilla " ,
2010-09-01 10:52:02 +02:00
download - > dl_dir , download - > pconnections [ 0 ] - > u . file ) ;
if ( rename ( out_filename , orig_filename ) = = - 1 )
{
download_show_message ( download , " Error While attempting to rename the file: %s " , strerror ( errno ) ) ;
}
2010-08-31 03:50:41 +02:00
download_show_message ( download , " Successfully renamed file " ) ;
/*Delete the logfile as we dont need it now */
2010-09-01 10:52:02 +02:00
if ( proz_log_delete_logfile ( download ) ! = 1 )
download_show_message ( download , " Error: Unable to delete the logfile: %s " , strerror ( errno ) ) ;
2010-08-31 03:50:41 +02:00
return DLDONE ;
}
/*TODO handle restartable connections */
for ( i = 0 ; i < download - > num_connections ; i + + )
{
dl_status status ;
uerr_t connection_err ;
pthread_mutex_lock ( download - > pconnections [ i ] - > status_change_mutex ) ;
status = download - > pconnections [ i ] - > status ;
pthread_mutex_unlock ( download - > pconnections [ i ] - > status_change_mutex ) ;
pthread_mutex_lock ( & download - > pconnections [ i ] - > access_mutex ) ;
connection_err = download - > pconnections [ i ] - > err ;
pthread_mutex_unlock ( & download - > pconnections [ i ] - > access_mutex ) ;
switch ( status )
2010-09-01 10:52:02 +02:00
{
case MAXTRYS :
break ;
case REMOTEFATAL :
/* handle the CANTRESUME err code */
if ( connection_err = = CANTRESUME )
{
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
/*FIXME Do we delete any downloaded portions here ? */
return CANTRESUME ;
}
else /*Handle the file not being found on the server */
if ( connection_err = = FTPNSFOD | | connection_err = = HTTPNSFOD )
{
if ( proz_download_all_dls_filensfod ( download ) = = TRUE )
{
download_show_message ( download ,
_
( " The file was not found in all the connections! " ) ) ;
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
return DLREMOTEFATAL ;
}
else
{
download_show_message ( download , _ ( " Relaunching download " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
}
else /*Handle the file not being found on the server */
if ( connection_err = = FTPCWDFAIL )
{
if ( proz_download_all_dls_ftpcwdfail ( download ) = = TRUE )
{
download_show_message ( download ,
_
( " Failed to change to the working directory on all the connections! " ) ) ;
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
return DLREMOTEFATAL ;
}
else
{
download_show_message ( download , _ ( " Relaunching download " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond , & download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
}
break ;
case LOCALFATAL :
proz_download_stop_downloads ( download ) ;
download_show_message ( download ,
_
( " Connection %d, had a local fatal error: %s .Aborting download. " ) ,
i ,
proz_strerror ( download - > pconnections [ i ] - > err ) ) ;
return DLLOCALFATAL ;
break ;
case LOGINFAIL :
/*
* First check if the ftp server did not allow any thread
* to login at all , then retry the curent thread
*/
if ( proz_download_all_dls_status ( download , LOGINFAIL ) = = TRUE )
{
download_show_message ( download ,
_
( " All logins rejected! Retrying connection " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
break ;
}
else
{
/*
* Ok so at least there is one download whos login has not been rejected ,
* so lets see if it has completed , if so we can relaunch this connection ,
* as the commonest reason for a ftp login being rejected is because , the
* ftp server has a limit on the number of logins permitted from the same
* IP address .
*/
/*
* Query the number of threads that are downloading
* if it is zero then relaunch this connection
*/
int dling_conns_count =
download_query_conns_status_count ( download , DOWNLOADING , NULL ) ;
if ( dling_conns_count > download - > max_simul_connections )
{
download - > max_simul_connections = dling_conns_count ;
break ;
}
if ( dling_conns_count = = 0
& &
( download_query_conns_status_count ( download , CONNECTING , NULL )
= = 0 )
& & ( download_query_conns_status_count ( download , LOGGININ , NULL )
= = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
if ( dling_conns_count < download - > max_simul_connections
& &
( download_query_conns_status_count
( download , CONNECTING , NULL ) = = 0 )
& &
( download_query_conns_status_count
( download , LOGGININ , NULL ) = = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
}
break ;
case CONREJECT :
/*
* First check if the ftp server did not allow any thread
* to login at all , then retry the curent thread
*/
if ( proz_download_all_dls_status ( download , CONREJECT ) = = TRUE )
{
download_show_message ( download ,
_
( " All connections attempts have been rejected! Retrying connection " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
break ;
}
else
{
/*
* Ok so at least there is one download whos connections attempt has not been rejected ,
* so lets see if it has completed , if so we can relaunch this connection ,
* as the commonest reason for a ftp login being rejected is because , the
* ftp server has a limit on the number of logins permitted from the same
* IP address .
*/
/*
* Query the number of threads that are downloading
* if it is zero then relaunch this connection
*/
int dling_conns_count =
download_query_conns_status_count ( download , DOWNLOADING , NULL ) ;
if ( dling_conns_count > download - > max_simul_connections )
{
download - > max_simul_connections = dling_conns_count ;
break ;
}
if ( dling_conns_count = = 0
& &
( download_query_conns_status_count ( download , CONNECTING , NULL )
= = 0 )
& & ( download_query_conns_status_count ( download , LOGGININ , NULL )
= = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
if ( dling_conns_count < download - > max_simul_connections
& &
( download_query_conns_status_count
( download , CONNECTING , NULL ) = = 0 )
& &
( download_query_conns_status_count
( download , LOGGININ , NULL ) = = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
}
break ;
default :
break ;
}
2010-08-31 03:50:41 +02:00
}
/*bandwith throttling */
download_calc_throttle_factor ( download ) ;
return DLINPROGRESS ;
}
pthread_mutex_t download_msg_mutex = PTHREAD_MUTEX_INITIALIZER ;
/*calls the msg_proc function if not null */
void download_show_message ( download_t * download , const char * format , . . . )
{
va_list args ;
char message [ MAX_MSG_SIZE + 1 ] ;
pthread_mutex_lock ( & download_msg_mutex ) ;
va_start ( args , format ) ;
vsnprintf ( message , MAX_MSG_SIZE , format , args ) ;
va_end ( args ) ;
if ( download - > msg_proc )
download - > msg_proc ( message , download - > cb_data ) ;
/*FIXME: Remove this later */
// printf("%s\n", message);
pthread_mutex_unlock ( & download_msg_mutex ) ;
}
/*This will return a pointer to the connection requested. */
connection_t * proz_download_get_connection ( download_t * download ,
2010-09-01 10:52:02 +02:00
int number )
2010-08-31 03:50:41 +02:00
{
assert ( number > = 0 & & number < download - > num_connections ) ;
2010-09-01 10:52:02 +02:00
return ( download - > pconnections [ number ] ) ;
2010-08-31 03:50:41 +02:00
}
/*Returns the total number of bytes got.*/
off_t proz_download_get_total_bytes_got ( download_t * download )
{
off_t total_bytes_got = 0 ;
int i ;
for ( i = 0 ; i < download - > num_connections ; i + + )
2010-09-01 10:52:02 +02:00
{
total_bytes_got + =
proz_connection_get_total_bytes_got ( download - > pconnections [ i ] ) ;
}
2010-08-31 03:50:41 +02:00
return total_bytes_got ;
}
/*Returns 1 if a previous download exits, 0 if not, and -1 on error */
int proz_download_prev_download_exists ( download_t * download )
{
2010-09-01 10:52:02 +02:00
/* Currently if a logfile exists it assumes that a previous uncompleted
2010-08-31 03:50:41 +02:00
download exists
*/
return proz_log_logfile_exists ( download ) ;
}
/*Returns the download speed in bytes per second */
float proz_download_get_average_speed ( download_t * download )
{
float speed ;
struct timeval cur_time ;
struct timeval diff_time ;
off_t total_remote_bytes_got =
2010-09-01 10:52:02 +02:00
proz_download_get_total_remote_bytes_got ( download ) ;
2010-08-31 03:50:41 +02:00
/*Has the download has been started.... */
if ( download - > start_time . tv_sec > 0 | | download - > start_time . tv_usec > 0 )
{
2010-09-01 10:52:02 +02:00
gettimeofday ( & cur_time , NULL ) ;
/*Get the diff. */
proz_timeval_subtract ( & diff_time , & cur_time , & download - > start_time ) ;
if ( diff_time . tv_sec > = 1 ) // || diff_time.tv_usec > 0)
{
speed = ( float ) total_remote_bytes_got / ( ( float ) diff_time . tv_sec +
( ( float ) diff_time .
tv_usec / 10e5 ) ) ;
}
else
speed = 0 ;
}
else
speed = 0 ; /*The DL hasnt started yet */
2010-08-31 03:50:41 +02:00
return speed ;
}
2010-09-01 10:52:02 +02:00
/* This can be called to erase the portions of the main file
2010-08-31 03:50:41 +02:00
that have been got .
2010-09-01 10:52:02 +02:00
*/
2010-08-31 03:50:41 +02:00
int proz_download_delete_dl_file ( download_t * download )
{
char * out_file ;
2010-09-01 10:52:02 +02:00
out_file = kmalloc ( PATH_MAX ) ;
2010-08-31 03:50:41 +02:00
snprintf ( out_file , PATH_MAX , " %s/%s.prozilla " ,
2010-09-01 10:52:02 +02:00
download - > dl_dir , download - > u . file ) ;
2010-08-31 03:50:41 +02:00
if ( unlink ( out_file ) = = - 1 )
{
/*
2010-09-01 10:52:02 +02:00
* if the file is not present no need for a error message ; - )
2010-08-31 03:50:41 +02:00
*/
if ( errno = = ENOENT )
2010-09-01 10:52:02 +02:00
{
return 1 ;
}
2010-08-31 03:50:41 +02:00
else
2010-09-01 10:52:02 +02:00
{
download_show_message ( download ,
_
( " unable to delete the file %s. Reason-: %s " ) ,
out_file , strerror ( errno ) ) ;
return - 1 ;
}
2010-08-31 03:50:41 +02:00
}
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
return 1 ;
}
/*This will wait till all the downloaded threads are not running */
void proz_download_wait_till_all_end ( download_t * download )
{
int i ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
/*Wait till the end of all the threads */
for ( i = 0 ; i < download - > num_connections ; i + + )
2010-09-01 10:52:02 +02:00
{
pthread_join ( download - > threads [ i ] , NULL ) ;
}
2010-08-31 03:50:41 +02:00
}
/*Creates the joining thread */
void proz_download_join_downloads ( download_t * download )
{
download - > building = TRUE ;
2010-09-01 10:52:02 +02:00
pthread_create ( & download - > join_thread , NULL ,
( void * ( * ) ( void * ) ) download_join_downloads ,
( void * ) download ) ;
2010-08-31 03:50:41 +02:00
}
/*This function will call download_join_downloads with a handler to join the downloaded files*/
void download_join_downloads ( download_t * download )
{
// pthread_cleanup_push(cleanup_joining_thread, (void *) download);
join_downloads ( download ) ;
// pthread_cleanup_pop(0);
}
/*This function will join the downloaded files*/
void join_downloads ( download_t * download )
{
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & download - > access_mutex ) ;
2010-08-31 03:50:41 +02:00
download - > building = 0 ;
pthread_mutex_unlock ( & download - > access_mutex ) ;
return ;
}
2010-09-01 10:52:02 +02:00
/*****************************************************************************
Returns the total number of bytes that has being got from the server
by the all the connections managed by this download
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-08-31 03:50:41 +02:00
off_t proz_download_get_total_remote_bytes_got ( download_t * download )
{
off_t total_bytes_recv = 0 ;
int i ;
for ( i = 0 ; i < download - > num_connections ; i + + )
2010-09-01 10:52:02 +02:00
{
proz_debug ( " DOWNLOAD_TOTAL_BYTES_RECV=%lld for connection %d " , total_bytes_recv , i ) ;
total_bytes_recv + =
proz_connection_get_total_remote_bytes_got ( download - >
pconnections [ i ] ) ;
}
2010-08-31 03:50:41 +02:00
return total_bytes_recv ;
}
/*If all the downlaods status is equal to status ,returns TRUE */
int proz_download_all_dls_status ( download_t * download , dl_status status )
{
int i ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
pthread_mutex_lock ( & download - > status_change_mutex ) ;
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
if ( download - > pconnections [ i ] - > status ! = status )
{
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
return FALSE ;
}
2010-08-31 03:50:41 +02:00
}
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
return TRUE ;
}
boolean proz_download_all_dls_filensfod ( download_t * download )
{
int i ;
uerr_t err ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
/*Lock mutex */
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & download - > pconnections [ i ] - > access_mutex ) ;
err = download - > pconnections [ i ] - > err ;
pthread_mutex_unlock ( & download - > pconnections [ i ] - > access_mutex ) ;
if ( err ! = FTPNSFOD & & err ! = HTTPNSFOD )
{
return FALSE ;
}
2010-08-31 03:50:41 +02:00
}
return TRUE ;
}
boolean proz_download_all_dls_ftpcwdfail ( download_t * download )
{
int i ;
uerr_t err ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
/*Lock mutex */
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & download - > pconnections [ i ] - > access_mutex ) ;
err = download - > pconnections [ i ] - > err ;
pthread_mutex_unlock ( & download - > pconnections [ i ] - > access_mutex ) ;
if ( err ! = FTPNSFOD & & err ! = FTPCWDFAIL )
{
return FALSE ;
}
2010-08-31 03:50:41 +02:00
}
return TRUE ;
}
/*If all the downlaods conections err status is equal to in_err (ie all encountered the same error) ,returns TRUE */
boolean proz_download_all_dls_err ( download_t * download , uerr_t in_err )
{
2010-09-01 10:52:02 +02:00
int i ;
2010-08-31 03:50:41 +02:00
uerr_t err ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
/*Lock mutex */
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & download - > pconnections [ i ] - > access_mutex ) ;
err = download - > pconnections [ i ] - > err ;
pthread_mutex_unlock ( & download - > pconnections [ i ] - > access_mutex ) ;
if ( err ! = in_err )
{
return FALSE ;
}
2010-08-31 03:50:41 +02:00
}
return TRUE ;
}
/* Returns the number of connections whose status is status ie (connecting to the server specified),
2010-09-01 10:52:02 +02:00
if server is NULL then it returns the total number of connections that are having the status which is equal the to the status specified */
2010-08-31 03:50:41 +02:00
int download_query_conns_status_count ( download_t * download ,
2010-09-01 10:52:02 +02:00
dl_status status , char * server )
2010-08-31 03:50:41 +02:00
{
int i ;
int count = 0 ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
pthread_mutex_lock ( & download - > status_change_mutex ) ;
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
if ( download - > pconnections [ i ] - > status = = status )
{
if ( server = = NULL
| | ( strcasecmp ( server , download - > pconnections [ i ] - > u . host ) = = 0 ) )
count + + ;
}
2010-08-31 03:50:41 +02:00
}
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
return count ;
}
void proz_download_set_msg_proc ( download_t * download ,
2010-09-01 10:52:02 +02:00
message_proc msg_proc , void * cb_data )
2010-08-31 03:50:41 +02:00
{
assert ( download ! = NULL ) ;
download - > msg_proc = msg_proc ;
download - > cb_data = cb_data ;
}
/*Returns the number of seconds left remaining in the download,
2010-09-01 10:52:02 +02:00
if it cannot be calculated say if the file size of not known , it returns - 1
*/
2010-08-31 03:50:41 +02:00
off_t proz_download_get_est_time_left ( download_t * download )
{
long secs_left ;
float average_speed ;
off_t total_bytes_got ;
if ( download - > main_file_size = = - 1 )
return - 1 ;
total_bytes_got = proz_download_get_total_bytes_got ( download ) ;
average_speed = proz_download_get_average_speed ( download ) ;
if ( average_speed = = 0 )
return - 1 ;
return secs_left =
2010-09-01 10:52:02 +02:00
( off_t ) ( ( download - > main_file_size -
total_bytes_got ) / average_speed ) ;
2010-08-31 03:50:41 +02:00
}
void proz_download_free_download ( download_t * download , boolean complete )
{
assert ( download ) ;
/*TODO free the URL */
if ( download - > dl_dir )
kfree ( download - > dl_dir ) ;
if ( download - > output_dir )
kfree ( download - > output_dir ) ;
if ( download - > log_dir )
kfree ( download - > log_dir ) ;
if ( download - > file_build_msg )
kfree ( download - > file_build_msg ) ;
if ( download - > threads )
kfree ( download - > threads ) ;
/*Now handle the freeing of the connections */
if ( download - > num_connections > 0 & & download - > pconnections )
{
2010-09-01 10:52:02 +02:00
int i ;
for ( i = 0 ; i < download - > num_connections ; i + + )
{
proz_connection_free_connection ( download - > pconnections [ i ] , 0 ) ;
}
kfree ( download - > pconnections ) ;
2010-08-31 03:50:41 +02:00
}
if ( complete = = TRUE )
kfree ( download ) ;
}
void download_calc_throttle_factor ( download_t * download )
{
int i ;
int num_slow_cons = 0 ;
long t_slow_rates = 0 ;
long limit_high_cons_rate ;
long avg_rate ;
int num_dl_cons =
2010-09-01 10:52:02 +02:00
download_query_conns_status_count ( download , DOWNLOADING , NULL ) ;
2010-08-31 03:50:41 +02:00
if ( num_dl_cons = = 0 )
return ;
avg_rate = download - > max_allowed_bps / num_dl_cons ;
if ( download - > max_allowed_bps = = 0 )
{
2010-09-01 10:52:02 +02:00
for ( i = 0 ; i < download - > num_connections ; i + + )
{
pthread_mutex_lock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
download - > pconnections [ i ] - > max_allowed_bps = 0 ;
pthread_mutex_unlock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
}
return ;
2010-08-31 03:50:41 +02:00
}
/*MAKE IR USE THE NUMBER OF ACTIVE DOWNLOAdING CONENCTIONS: Done */
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
if ( ( proz_connection_get_status ( download - > pconnections [ i ] ) = =
DOWNLOADING ) & & download - > pconnections [ i ] - > rate_bps < avg_rate )
{
t_slow_rates + = download - > pconnections [ i ] - > rate_bps ;
num_slow_cons + + ;
}
pthread_mutex_unlock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
2010-08-31 03:50:41 +02:00
}
/*fixme mutex to preven this conenctions */
if ( num_slow_cons > num_dl_cons )
num_dl_cons = num_slow_cons ;
/*If all the connections are slower then no need to do anything */
if ( num_slow_cons = = num_dl_cons )
{
2010-09-01 10:52:02 +02:00
for ( i = 0 ; i < download - > num_connections ; i + + )
{
pthread_mutex_lock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
download - > pconnections [ i ] - > max_allowed_bps = 0 ;
pthread_mutex_unlock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
}
return ;
2010-08-31 03:50:41 +02:00
}
limit_high_cons_rate =
2010-09-01 10:52:02 +02:00
( download - > max_allowed_bps - t_slow_rates ) / ( num_dl_cons -
num_slow_cons ) ;
2010-08-31 03:50:41 +02:00
/*
proz_debug ( " total slow connections = %ld " , num_slow_cons ) ;
proz_debug ( " total slow rates = %ld " , t_slow_rates ) ;
proz_debug ( " limit_high_cons_rate = %ld " , limit_high_cons_rate ) ;
*/
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
if ( ( proz_connection_get_status ( download - > pconnections [ i ] ) = =
DOWNLOADING ) & & download - > pconnections [ i ] - > rate_bps > = avg_rate )
{
download - > pconnections [ i ] - > max_allowed_bps = limit_high_cons_rate ;
}
pthread_mutex_unlock ( & ( download - > pconnections [ i ] - > access_mutex ) ) ;
2010-08-31 03:50:41 +02:00
}
}
2010-09-01 10:52:02 +02:00
/*This function will check if the target output file,
ie : the file that we are going to rebuild to exists .
Returns ,
1 = file exists
0 = file does not exists
- 1 = error , ie cant have permissions to stat the file etc etc
*/
2010-08-31 03:50:41 +02:00
int proz_download_target_exist ( download_t * download )
{
char out_file_name [ PATH_MAX ] ;
struct stat st_buf ;
int ret ;
snprintf ( out_file_name , PATH_MAX , " %s/%s " , download - > output_dir ,
2010-09-01 10:52:02 +02:00
download - > u . file ) ;
2010-08-31 03:50:41 +02:00
ret = stat ( out_file_name , & st_buf ) ;
if ( ret = = - 1 )
2010-09-01 10:52:02 +02:00
{
if ( errno = = ENOENT )
return 0 ;
else
return - 1 ;
}
2010-08-31 03:50:41 +02:00
/*File was statable so it exists */
return 1 ;
}
2010-09-01 10:52:02 +02:00
/*This function will delete the target output file,
Returns ,
1 = sucessfully delted the file
0 = file does not exist
- 1 = error , ie cant have permissions to delete the file etc etc
*/
2010-08-31 03:50:41 +02:00
int proz_download_delete_target ( download_t * download )
{
char out_file_name [ PATH_MAX ] ;
int ret ;
snprintf ( out_file_name , PATH_MAX , " %s/%s " , download - > output_dir ,
2010-09-01 10:52:02 +02:00
download - > u . file ) ;
2010-08-31 03:50:41 +02:00
ret = remove ( out_file_name ) ;
if ( ret = = - 1 )
2010-09-01 10:52:02 +02:00
{
if ( errno = = ENOENT )
return 0 ;
else
return - 1 ;
}
2010-08-31 03:50:41 +02:00
/*File was statable so it exists */
return 1 ;
}
/*Tries to switch to another server which is downloading or has completed, returns 1 on sucesss, or -1 on failure
*/
int download_switch_server_ftpsearch ( download_t * download , int bad_connection )
{
2010-09-01 10:52:02 +02:00
int j , usable_server ;
usable_server = - 1 ;
/*Search for a server which is downloading or completed and try to switch to it
*/
pthread_mutex_lock ( & download - > status_change_mutex ) ;
for ( j = 0 ; j < download - > num_connections ; j + + )
{
if ( download - > pconnections [ j ] - > status = = DOWNLOADING | |
download - > pconnections [ j ] - > status = = COMPLETED )
{
usable_server = j ;
}
}
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
if ( usable_server ! = - 1 )
{
/*We have a server which is DLING */
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ bad_connection ] , NULL ) ;
/*copy url and relaunch */
proz_free_url ( & download - > pconnections [ bad_connection ] - > u , 0 ) ;
memcpy ( & download - > pconnections [ bad_connection ] - > u ,
proz_copy_url ( & download - >
pconnections [ usable_server ] - > u ) ,
sizeof ( urlinfo ) ) ;
proz_debug
( " Found server %s which is downloading will relaunch based on it " ,
download - > pconnections [ usable_server ] - > u . host ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
/*Relaunch thread */
if ( pthread_create
( & download - > threads [ bad_connection ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ bad_connection ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ bad_connection ] - > connecting_cond , & download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
return 1 ;
}
else
{
/*Shit! no servers are downloading or completed so what shall we do? we shall do nothing and wait for one connectection at least to start downloading */
return - 1 ;
}
}
2010-08-31 03:50:41 +02:00
/* returns one of DLINPROGRESS, DLERR, DLDONE, DLREMOTEFATAL, DLLOCALFATAL*/
uerr_t download_handle_threads_ftpsearch ( download_t * download )
{
int i ;
for ( i = 0 ; i < download - > num_connections ; i + + )
{
2010-09-01 10:52:02 +02:00
/*Set the DL start time if it is not done so */
pthread_mutex_lock ( download - > pconnections [ i ] - > status_change_mutex ) ;
if ( download - > pconnections [ i ] - > status = = DOWNLOADING
& & download - > start_time . tv_sec = = 0
& & download - > start_time . tv_usec = = 0 )
{
gettimeofday ( & download - > start_time , NULL ) ;
}
pthread_mutex_unlock ( download - > pconnections [ i ] - > status_change_mutex ) ;
2010-08-31 03:50:41 +02:00
}
/*If all the connections are completed then end them, and return complete */
if ( ( proz_download_all_dls_status ( download , COMPLETED ) ) = = TRUE )
2010-09-01 10:52:02 +02:00
{
2010-08-31 03:50:41 +02:00
char * out_filename ;
char * orig_filename ;
2010-09-01 10:52:02 +02:00
download_show_message ( download ,
" All the conenctions have retreived the file "
" ..waiting for them to end " ) ;
proz_download_wait_till_all_end ( download ) ;
download_show_message ( download , " All the threads have being ended. " ) ;
2010-08-31 03:50:41 +02:00
/*Close and rename file to original */
flockfile ( download - > pconnections [ 0 ] - > fp ) ;
fclose ( download - > pconnections [ 0 ] - > fp ) ;
funlockfile ( download - > pconnections [ 0 ] - > fp ) ;
2010-09-01 10:52:02 +02:00
out_filename = kmalloc ( PATH_MAX ) ;
orig_filename = kmalloc ( PATH_MAX ) ;
2010-08-31 03:50:41 +02:00
snprintf ( orig_filename , PATH_MAX , " %s/%s " ,
2010-09-01 10:52:02 +02:00
download - > dl_dir , download - > pconnections [ 0 ] - > u . file ) ;
2010-08-31 03:50:41 +02:00
snprintf ( out_filename , PATH_MAX , " %s/%s.prozilla " ,
2010-09-01 10:52:02 +02:00
download - > dl_dir , download - > pconnections [ 0 ] - > u . file ) ;
if ( rename ( out_filename , orig_filename ) = = - 1 )
{
download_show_message ( download , " Error While attempting to rename the file: %s " , strerror ( errno ) ) ;
}
2010-08-31 03:50:41 +02:00
download_show_message ( download , " Successfully renamed file " ) ;
/*Delete the logfile as we dont need it now */
2010-09-01 10:52:02 +02:00
if ( proz_log_delete_logfile ( download ) ! = 1 )
download_show_message ( download , " Error: Unable to delete the logfile: %s " , strerror ( errno ) ) ;
return DLDONE ;
}
2010-08-31 03:50:41 +02:00
/*TODO handle restartable connections */
for ( i = 0 ; i < download - > num_connections ; i + + )
2010-09-01 10:52:02 +02:00
{
dl_status status ;
uerr_t connection_err ;
pthread_mutex_lock ( download - > pconnections [ i ] - > status_change_mutex ) ;
status = download - > pconnections [ i ] - > status ;
pthread_mutex_unlock ( download - > pconnections [ i ] - > status_change_mutex ) ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & download - > pconnections [ i ] - > access_mutex ) ;
connection_err = download - > pconnections [ i ] - > err ;
pthread_mutex_unlock ( & download - > pconnections [ i ] - > access_mutex ) ;
2010-08-31 03:50:41 +02:00
2010-09-01 10:52:02 +02:00
switch ( status )
{
case MAXTRYS :
break ;
case REMOTEFATAL :
/* handle the CANTRESUME err code */
if ( connection_err = = CANTRESUME )
{
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
/*FIXME Do we delete any downloaded portions here ? */
return CANTRESUME ;
}
else /*Handle the file not being found on the server */
if ( connection_err = = FTPNSFOD | | connection_err = = HTTPNSFOD )
{
if ( proz_download_all_dls_filensfod ( download ) = = TRUE )
{
download_show_message ( download ,
_
( " The file was not found in all the connections! " ) ) ;
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
return DLREMOTEFATAL ;
}
else
{
/*Now we have to be careful */
int server_pos , cur_path_pos ;
server_pos =
ftpsearch_get_server_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u .
host ) ;
cur_path_pos =
ftpsearch_get_path_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u . host ,
download - > pconnections [ i ] - > u . dir ) ;
assert ( cur_path_pos ! = - 1 ) ;
proz_debug ( " Server pos = %d, cur_path_pos=%d " , server_pos ,
cur_path_pos ) ;
/*mark path as not valid */
download - > ftps_info - > mirrors [ server_pos ] . paths [ cur_path_pos ] .
valid = FALSE ;
/*See if more paths are avail */ ;
if ( cur_path_pos <
( download - > ftps_info - > mirrors [ server_pos ] . num_paths - 1 ) )
{
char * url_buf ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
/*additional paths avail to try */
download_show_message ( download ,
_
( " Trying additional paths available on this server " ) ) ;
proz_debug ( " Trying path %s " ,
download - > ftps_info - > mirrors [ server_pos ] .
paths [ cur_path_pos + 1 ] ) ;
url_buf =
malloc ( strlen
( download - > ftps_info - > mirrors [ server_pos ] .
server_name ) +
strlen ( download - > ftps_info - > mirrors [ server_pos ] .
paths [ cur_path_pos + 1 ] . path ) +
strlen ( download - > pconnections [ i ] - > u . file ) + 11 + 1 ) ;
sprintf ( url_buf , " ftp://%s/%s/%s " ,
download - > ftps_info - > mirrors [ server_pos ] . server_name ,
download - > ftps_info - > mirrors [ server_pos ] .
paths [ cur_path_pos + 1 ] . path ,
download - > pconnections [ i ] - > u . file ) ;
proz_debug ( " Target url for relaunching is %s " , url_buf ) ;
/*FIXME */
proz_parse_url ( url_buf , & download - > pconnections [ i ] - > u , 0 ) ;
free ( url_buf ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
/*Relaunch thread */
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
{
/*download_show_message(download,
_
( " No additional paths on this server available, so will try to switch to another server " ) ) ; */
/*Find any server that is downloading or completed and use it */
download_switch_server_ftpsearch ( download , i ) ;
}
}
}
else /*Handle the file not being found on the server */
if ( connection_err = = FTPCWDFAIL )
{
if ( proz_download_all_dls_ftpcwdfail ( download ) = = TRUE )
{
download_show_message ( download ,
_
( " Failed to change to the working directory on all the connections! " ) ) ;
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
return DLREMOTEFATAL ;
}
else
{
/*Now we have to be careful */
int server_pos , cur_path_pos ;
server_pos =
ftpsearch_get_server_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u .
host ) ;
assert ( server_pos ! = - 1 ) ;
cur_path_pos =
ftpsearch_get_path_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u . host ,
download - > pconnections [ i ] - > u . dir ) ;
assert ( cur_path_pos ! = - 1 ) ;
proz_debug ( " Server pos = %d, cur_path_pos=%d " , server_pos ,
cur_path_pos ) ;
/*mark path as not valid */
download - > ftps_info - > mirrors [ server_pos ] . paths [ cur_path_pos ] .
valid = FALSE ;
/*See if more paths are avail */ ;
if ( cur_path_pos <
( download - > ftps_info - > mirrors [ server_pos ] . num_paths - 1 ) )
{
char * url_buf ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
/*additional paths avail to try */
download_show_message ( download ,
_
( " Trying additional paths available on this server " ) ) ;
proz_debug ( " Trying path %s " ,
download - > ftps_info - > mirrors [ server_pos ] .
paths [ cur_path_pos + 1 ] ) ;
url_buf =
malloc ( strlen
( download - > ftps_info - > mirrors [ server_pos ] .
server_name ) +
strlen ( download - > ftps_info - > mirrors [ server_pos ] .
paths [ cur_path_pos + 1 ] . path ) +
strlen ( download - > pconnections [ i ] - > u . file ) + 11 + 1 ) ;
sprintf ( url_buf , " ftp://%s/%s/%s " ,
download - > ftps_info - > mirrors [ server_pos ] . server_name ,
download - > ftps_info - > mirrors [ server_pos ] .
paths [ cur_path_pos + 1 ] . path ,
download - > pconnections [ i ] - > u . file ) ;
proz_debug ( " Target url for relaunching is %s " , url_buf ) ;
/*FIXME */
proz_parse_url ( url_buf , & download - > pconnections [ i ] - > u , 0 ) ;
free ( url_buf ) ;
/*Relaunch thread */
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
}
else
{
/* download_show_message(download, _("No additional paths on this server available, so will try to switch to another server")); */
proz_debug
( " No additional paths on this server available, so will try to switch to another server " ) ;
/*Find any server that is downloading or completed and use it */
download_switch_server_ftpsearch ( download , i ) ;
}
}
}
else if ( connection_err = = FTPRESTFAIL )
{
/*Handle the server not supporting REST */
if ( proz_download_all_dls_err ( download , FTPRESTFAIL ) = = TRUE )
{
download_show_message ( download ,
_
( " The server(s) do not support REST on all the connections! " ) ) ;
/*Terminate the connections */
proz_download_stop_downloads ( download ) ;
return DLREMOTEFATAL ;
}
else
{
/*Now we have to be careful */
int server_pos ;
server_pos =
ftpsearch_get_server_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u .
host ) ;
proz_debug ( " Server pos = %d " , server_pos ) ;
/*mark server as not supporting resume */
download - > ftps_info - > mirrors [ server_pos ] . resume_supported =
FALSE ;
{
download_show_message ( download ,
_
( " This server does not support resuming downloads, so will switch to another server " ) ) ;
download_switch_server_ftpsearch ( download , i ) ;
}
}
}
break ;
case LOCALFATAL :
proz_download_stop_downloads ( download ) ;
download_show_message ( download ,
_
( " Connection %d, had a local fatal error: %s .Aborting download. " ) ,
i ,
proz_strerror ( download - > pconnections [ i ] - > err ) ) ;
return DLLOCALFATAL ;
break ;
case LOGINFAIL :
/*
* First check if the ftp server did not allow any thread
* to login at all , then retry the curent thread
*/
if ( proz_download_all_dls_status ( download , LOGINFAIL ) = = TRUE )
{
download_show_message ( download ,
_
( " All logins rejected! Retrying connection " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
break ;
}
else
{
int j , usable_server ;
/*Find any server that is downloading or completed and use it instead */
usable_server = - 1 ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
for ( j = 0 ; j < download - > num_connections ; j + + )
{
if ( ( download - > pconnections [ j ] - > status = = DOWNLOADING | |
download - > pconnections [ j ] - > status = = COMPLETED ) & & j ! = i )
{
usable_server = j ;
}
}
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
if ( usable_server ! = - 1 )
{
/*We have a server which is DLING */
download_show_message ( download ,
_
( " This server has rejected the login attempt, so will switch to another server " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
/*copy url and relaunch */
proz_free_url ( & download - > pconnections [ i ] - > u , 0 ) ;
memcpy ( & download - > pconnections [ i ] - > u ,
proz_copy_url ( & download - >
pconnections [ usable_server ] - > u ) ,
sizeof ( urlinfo ) ) ;
proz_debug
( " Found server %s which is downloading will relaunch based on it " ,
download - > pconnections [ usable_server ] - > u . host ) ;
/*Relaunch thread */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
{
/*
* Ok so at least there is one download whos login has not been rejected ,
* so lets see if it has completed , if so we can relaunch this connection ,
* as the commonest reason for a ftp login being rejected is because , the
* ftp server has a limit on the number of logins permitted from the same
* IP address .
*/
/*
* Query the number of threads that are downloading
* if it is zero then relaunch this connection
*/
int server_pos ;
int dling_conns_count =
download_query_conns_status_count ( download , DOWNLOADING ,
download - >
pconnections [ i ] - > u . host ) ;
server_pos =
ftpsearch_get_server_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u . host ) ;
if ( dling_conns_count >
download - > ftps_info - > mirrors [ server_pos ] . max_simul_connections )
{
download - > ftps_info - > mirrors [ server_pos ] . max_simul_connections =
dling_conns_count ;
break ;
}
if ( dling_conns_count = = 0
& &
( download_query_conns_status_count
( download , CONNECTING , download - > pconnections [ i ] - > u . host ) = = 0 )
& &
( download_query_conns_status_count
( download , LOGGININ , download - > pconnections [ i ] - > u . host ) = = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
if ( dling_conns_count <
download - > ftps_info - > mirrors [ server_pos ] .
max_simul_connections
& &
( download_query_conns_status_count
( download , CONNECTING ,
download - > pconnections [ i ] - > u . host ) = = 0 )
& &
( download_query_conns_status_count
( download , LOGGININ ,
download - > pconnections [ i ] - > u . host ) = = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
}
}
break ;
case CONREJECT :
/*
* First check if the ftp server did not allow any thread
* to login at all , then retry the curent thread
*/
if ( proz_download_all_dls_status ( download , CONREJECT ) = = TRUE )
{
download_show_message ( download ,
_
( " All connections attempts have been rejected! Retrying connection " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
break ;
}
else
{
int j , usable_server ;
/*Find any server that is downloading or completed and use it instead */
usable_server = - 1 ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
for ( j = 0 ; j < download - > num_connections ; j + + )
{
if ( ( download - > pconnections [ j ] - > status = = DOWNLOADING | |
download - > pconnections [ j ] - > status = = COMPLETED ) & & j ! = i )
{
usable_server = j ;
}
}
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
if ( usable_server ! = - 1 )
{
/*We have a server which is DLING */
download_show_message ( download ,
_
( " This server has rejected the connection attempt, so will switch to another server " ) ) ;
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
/*copy url and relaunch */
proz_free_url ( & download - > pconnections [ i ] - > u , 0 ) ;
memcpy ( & download - > pconnections [ i ] - > u ,
proz_copy_url ( & download - >
pconnections [ usable_server ] - > u ) ,
sizeof ( urlinfo ) ) ;
proz_debug
( " Found server %s which is downloading will relaunch based on it " ,
download - > pconnections [ usable_server ] - > u . host ) ;
/*Relaunch thread */
pthread_mutex_lock ( & download - > status_change_mutex ) ;
if ( pthread_create
( & download - > threads [ i ] , NULL , ( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
{
/*
* Ok so at least there is one download whos connections attempt has not been rejected ,
* so lets see if it has completed , if so we can relaunch this connection ,
* as the commonest reason for a ftp login being rejected is because , the
* ftp server has a limit on the number of logins permitted from the same
* IP address .
*/
/*
* Query the number of threads that are downloading
* if it is zero then relaunch this connection
*/
int server_pos ;
int dling_conns_count =
download_query_conns_status_count ( download , DOWNLOADING ,
download - >
pconnections [ i ] - > u . host ) ;
server_pos =
ftpsearch_get_server_position ( download - > ftps_info ,
download - > pconnections [ i ] - > u . host ) ;
if ( dling_conns_count >
download - > ftps_info - > mirrors [ server_pos ] . max_simul_connections )
{
download - > ftps_info - > mirrors [ server_pos ] . max_simul_connections =
dling_conns_count ;
break ;
}
if ( dling_conns_count = = 0
& &
( download_query_conns_status_count
( download , CONNECTING , download - > pconnections [ i ] - > u . host ) = = 0 )
& &
( download_query_conns_status_count
( download , LOGGININ , download - > pconnections [ i ] - > u . host ) = = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
else
if ( dling_conns_count <
download - > ftps_info - > mirrors [ server_pos ] .
max_simul_connections
& &
( download_query_conns_status_count
( download , CONNECTING ,
download - > pconnections [ i ] - > u . host ) = = 0 )
& &
( download_query_conns_status_count
( download , LOGGININ ,
download - > pconnections [ i ] - > u . host ) = = 0 ) )
{
/* Make sure this thread has terminated */
pthread_join ( download - > threads [ i ] , NULL ) ;
pthread_mutex_lock ( & download - > status_change_mutex ) ;
download_show_message ( download , _ ( " Relaunching download " ) ) ;
if ( pthread_create ( & download - > threads [ i ] , NULL ,
( void * ) & ftp_loop ,
( void * ) ( download - > pconnections [ i ] ) ) ! = 0 )
proz_die ( _ ( " Error: Not enough system resources " ) ) ;
pthread_cond_wait ( & download - > pconnections [ i ] - > connecting_cond ,
& download - > status_change_mutex ) ;
pthread_mutex_unlock ( & download - > status_change_mutex ) ;
}
}
}
break ;
default :
break ;
}
2010-08-31 03:50:41 +02:00
}
/*bandwith throttling */
download_calc_throttle_factor ( download ) ;
return DLINPROGRESS ;
}
/******************************************************************************
2010-09-01 10:52:02 +02:00
This will setup a download based on the connection info and the ftpsearch results .
2010-08-31 03:50:41 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int proz_download_setup_connections_ftpsearch ( download_t * download ,
2010-09-01 10:52:02 +02:00
connection_t * connection ,
ftps_request_t * request ,
int req_connections )
2010-08-31 03:50:41 +02:00
{
int num_connections , i , num_usable_mirrors = 0 ;
off_t bytes_per_connection ;
off_t bytes_left ;
FILE * fp ;
char * out_file ;
struct stat stat_buf ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
/*TODO Check for log file and use same number of threads */
proz_debug ( " proz_download_setup_connections_ftpsearch " ) ;
download - > main_file_size = connection - > main_file_size ;
download - > ftps_info = request ;
num_connections = req_connections ;
/*Are there any mirrors that are working? */
/**/
if ( request - > num_mirrors > 0
& & request - > mirrors [ 0 ] . status = = RESPONSEOK )
{
2010-09-01 10:52:02 +02:00
proz_debug ( " got mirrors " ) ;
2010-08-31 03:50:41 +02:00
/*We should get the info and allocate here */
download - > resume_support = TRUE ;
bytes_per_connection = connection - > main_file_size / num_connections ;
bytes_left = connection - > main_file_size % num_connections ;
/* Get the number of mirros that are within 200% ping speed of the fastest */
for ( i = 0 ; i < request - > num_mirrors ; i + + )
2010-09-01 10:52:02 +02:00
{
if ( ( request - > mirrors [ i ] . status = = RESPONSEOK ) & &
( request - > mirrors [ i ] . milli_secs < =
( request - > mirrors [ 0 ] . milli_secs +
( ( request - > mirrors [ 0 ] . milli_secs * 100 ) / 100 ) ) ) )
num_usable_mirrors + + ;
}
2010-08-31 03:50:41 +02:00
proz_debug ( " usable mirrors = %d " , num_usable_mirrors ) ;
proz_debug ( " num_connections = %d " , num_connections ) ;
download - > pconnections =
2010-09-01 10:52:02 +02:00
kmalloc ( sizeof ( connection_t * ) * num_connections ) ;
2010-08-31 03:50:41 +02:00
download - > num_connections = num_connections ;
for ( i = 0 ; i < num_connections ; i + + )
2010-09-01 10:52:02 +02:00
{
urlinfo * url = malloc ( sizeof ( urlinfo ) ) ;
char * url_buf ;
if ( i < num_usable_mirrors )
{
url_buf =
malloc ( strlen ( request - > mirrors [ i ] . server_name ) +
strlen ( request - > mirrors [ i ] . paths [ 0 ] . path ) +
strlen ( connection - > u . file ) + 11 + 1 ) ;
sprintf ( url_buf , " ftp://%s/%s/%s " , request - > mirrors [ i ] . server_name ,
request - > mirrors [ i ] . paths [ 0 ] . path , connection - > u . file ) ;
proz_debug ( " Target url is %s " , url_buf ) ;
/*FIXME */
proz_parse_url ( url_buf , url , 0 ) ;
free ( url_buf ) ;
download - > pconnections [ i ] = proz_connection_init ( url ,
& download - > status_change_mutex ) ;
}
else
{
int extra_mirror = 0 ;
/*FIXME improve allocation algorithm in this part */
url_buf =
malloc ( strlen ( request - > mirrors [ extra_mirror ] . server_name ) +
strlen ( request - > mirrors [ extra_mirror ] . paths [ 0 ] . path ) +
strlen ( connection - > u . file ) + 11 + 1 ) ;
sprintf ( url_buf , " ftp://%s/%s/%s " ,
request - > mirrors [ extra_mirror ] . server_name ,
request - > mirrors [ extra_mirror ] . paths [ 0 ] . path ,
connection - > u . file ) ;
proz_debug ( " Target url is %s " , url_buf ) ;
/*FIXME */
proz_parse_url ( url_buf , url , 0 ) ;
free ( url_buf ) ;
download - > pconnections [ i ] = proz_connection_init ( url ,
& download - > status_change_mutex ) ;
}
download - > resume_support = download - > pconnections [ i ] - > resume_support =
TRUE ;
memcpy ( & download - > pconnections [ i ] - > hs , & connection - > hs ,
sizeof ( http_stat_t ) ) ;
out_file = kmalloc ( PATH_MAX ) ;
snprintf ( out_file , PATH_MAX , " %s/%s.prozilla " ,
download - > dl_dir , connection - > u . file ) ;
//First see if the file exists then we dont create a new one else we do
if ( stat ( out_file , & stat_buf ) = = - 1 )
{
/* the call failed */
/* if the error is due to the file not been present then there is no
need to do anything . . just continue , otherwise return error ( - 1 )
*/
if ( errno = = ENOENT )
{
//File not exists so create it
if ( !
( fp =
fopen ( out_file , " w+ " ) ) )
{
download_show_message ( download ,
_
( " Unable to open file %s: %s! " ) ,
out_file , strerror ( errno ) ) ;
return - 1 ;
}
}
else
return - 1 ;
}
else
{
//TODO: File exists : so stat it and if it doesnt match file size warna boput it...
if ( !
( fp =
fopen ( out_file , " r+ " ) ) )
{
download_show_message ( download ,
_
( " Unable to open file %s: %s! " ) ,
out_file , strerror ( errno ) ) ;
return - 1 ;
}
}
//TRY setting the offset;
if ( download - > main_file_size ! = - 1 )
{
if ( fseeko ( fp , download - > main_file_size , SEEK_SET ) ! = 0 )
return - 1 ;
}
/*Make sure all writes go directly to the file */
setvbuf ( fp , NULL , _IONBF , 0 ) ;
download - > pconnections [ i ] - > localfile = kmalloc ( PATH_MAX ) ;
strcpy ( out_file , download - > pconnections [ i ] - > localfile ) ;
download - > pconnections [ i ] - > fp = fp ;
download - > pconnections [ i ] - > retry = TRUE ;
download - > pconnections [ i ] - > main_file_size = connection - > main_file_size ;
download - > pconnections [ i ] - > orig_remote_startpos = download - > pconnections [ i ] - > remote_startpos = i * bytes_per_connection ;
download - > pconnections [ i ] - > remote_endpos =
i * bytes_per_connection + bytes_per_connection ;
//Changing things here.....
download - > pconnections [ i ] - > local_startpos = download - > pconnections [ i ] - > remote_startpos ;
/*Set the connections message to be download->msg_proc calback */
proz_connection_set_msg_proc ( download - > pconnections [ i ] ,
download - > msg_proc , download - > cb_data ) ;
}
2010-08-31 03:50:41 +02:00
/* Add the remaining bytes to the last connection */
download - > pconnections [ - - i ] - > remote_endpos + = bytes_left ;
2010-09-01 10:52:02 +02:00
}
else
{
proz_debug ( " No mirrors, which were up are found " ) ;
download - > using_ftpsearch = FALSE ;
return proz_download_setup_connections_no_ftpsearch ( download ,
connection ,
req_connections ) ;
}
2010-08-31 03:50:41 +02:00
download - > using_ftpsearch = TRUE ;
return num_connections ;
}
uerr_t proz_download_get_join_status ( download_t * download )
{
int building_status ;
2010-09-01 10:52:02 +02:00
pthread_mutex_lock ( & download - > access_mutex ) ;
building_status = download - > building ;
pthread_mutex_unlock ( & download - > access_mutex ) ;
switch ( building_status )
{
case 1 :
return JOININPROGRESS ;
case 0 :
return JOINDONE ;
case - 1 :
return JOINERR ;
default :
proz_die ( " Bad building falg in download structure " ) ;
}
return - 1 ;
2010-08-31 03:50:41 +02:00
}
float proz_download_get_file_build_percentage ( download_t * download )
{
float percent_done ;
2010-09-01 10:52:02 +02:00
2010-08-31 03:50:41 +02:00
pthread_mutex_lock ( & download - > access_mutex ) ;
2010-09-01 10:52:02 +02:00
percent_done = 100 ;
2010-08-31 03:50:41 +02:00
pthread_mutex_unlock ( & download - > access_mutex ) ;
return percent_done ;
}
void proz_download_cancel_joining_thread ( download_t * download )
{
2010-09-01 10:52:02 +02:00
pthread_cancel ( download - > join_thread ) ;
pthread_join ( download - > join_thread , NULL ) ;
2010-08-31 03:50:41 +02:00
}
void proz_download_wait_till_end_joining_thread ( download_t * download )
{
2010-09-01 10:52:02 +02:00
pthread_join ( download - > join_thread , NULL ) ;
2010-08-31 03:50:41 +02:00
}