//====================================================================
//
// Copyright (C) 2006-2008, Frank.Ning
//
// Filename: axel.c
// Author: Frank.Ning <zegong.ning@dinglicom.com>
// Description:
//
// $Id: axel.c,v 1.9 2007/11/30 08:18:11 frank Exp $
//
//====================================================================
#include "axel.h"
static const char* const axel_c_version =
"$Id: axel.c,v 1.9 2007/11/30 08:18:11 frank Exp $";
/* Axel */
static void save_state( axel_t *axel );
#ifdef WIN32
static DWORD WINAPI setup_thread(LPVOID c );
#else
static void *setup_thread( void * );
#endif
static void axel_message( axel_t *axel, char *format, ... );
static void axel_divide( axel_t *axel );
static char *buffer = NULL;
/* Create a new axel_t structure */
axel_t *axel_new( conf_t *conf, int file_id,
const char *url , const char* local_file, Orention_t direct )
{
// search_t *res;
axel_t *axel;
// url_t *u;
int i, tmpfd;
char *s;
struct stat ft;
axel = malloc( sizeof( axel_t ) );
memset( axel, 0, sizeof( axel_t ) );
axel->conf = conf;
axel->conn = malloc( sizeof( conn_t ) * axel->conf->num_connections );
memset( axel->conn, 0, sizeof( conn_t ) * axel->conf->num_connections );
if( axel->conf->max_speed > 0 )
{
if( (float) axel->conf->max_speed / axel->conf->buffer_size < 0.5 )
{
if( axel->conf->verbose >= 2 )
axel_message( axel, _("Buffer resized for this speed.") );
axel->conf->buffer_size = axel->conf->max_speed;
}
axel->delay_time = (int) ( (float) 1000000 / axel->conf->max_speed * axel->conf->buffer_size * axel->conf->num_connections );
}
if( buffer == NULL )
buffer = malloc( max( MAX_STRING, axel->conf->buffer_size ) );
axel->url = malloc( sizeof( url_t ) );
axel->url->next = axel->url;
strcpy( axel->url->text, (char *) url );
axel->direct = direct;
axel->status = malloc( sizeof(conn_status_t) );
memset( axel->status, 0, sizeof(conn_status_t) );
for( i = 0; i < axel->conf->num_connections ; ++i )
{
axel->conn[ i ].file_id = file_id;
axel->conn[ i ].direct = direct;
axel->status->mask |= ( 1 << i );
}
#if 0
if( count == 0 )
{
axel->url = malloc( sizeof( url_t ) );
axel->url->next = axel->url;
strcpy( axel->url->text, (char *) url );
}
else
{
res = (search_t *) url;
u = axel->url = malloc( sizeof( url_t ) );
for( i = 0; i < count; i ++ )
{
strcpy( u->text, res[i].url );
if( i < count - 1 )
{
u->next = malloc( sizeof( url_t ) );
u = u->next;
}
else
{
u->next = axel->url;
}
}
}
#endif
axel->conn[0].conf = axel->conf;
axel->conn[0].status = axel->status;
if( !conn_set( &axel->conn[0], axel->url->text ) )
{
axel_message( axel, _("Could not parse URL:%s\n") , axel->url->text );
axel->ready = -1;
return( axel );
}
axel->conn[0].local_if = axel->conf->ip_addr;
// axel->conf->interfaces = axel->conf->interfaces->next;
if( *axel->conn[ 0 ].file != 0 )
{
strcpy( axel->filename, axel->conn[0].file );
http_decode( axel->filename );
}
#if 0
if( *axel->filename == 0 ) /* Index page == no fn */
strcpy( axel->filename, axel->conf->default_filename );
#endif
if( local_file != NULL &&
*local_file != 0 )
strcpy( axel->filename, local_file );
if( ( s = strchr( axel->filename, '?' ) ) != NULL && axel->conf->strip_cgi_parameters )
*s = 0; /* Get rid of CGI parameters */
if( !conn_init( &axel->conn[0] ) )
{
axel_message( axel, axel->conn[0].message );
axel->ready = -1;
return( axel );
}
if( axel->direct == AUTO || axel->direct == UPLOAD )
{
axel->direct = UPLOAD;
if( ( tmpfd = open( axel->filename, O_RDONLY ) ) != -1 )
{
// upload, then find the file size
fstat( tmpfd, &ft );
if( ft.st_size != 0 )
{
axel->conn[ 0 ].size = ft.st_size;
axel->conf->num_connections = 1;
axel->conn = realloc( axel->conn, sizeof( conn_t ) );
if( *axel->conn[ 0 ].file == 0 )
strcpy( axel->conn[ 0 ].file, axel->filename );
}
else
axel->ready = -1;
close( tmpfd );
}
else
axel->ready = -1;
}
/* This does more than just checking the file size, it all depends
on the protocol used. */
if( axel->direct == DOWNLOAD &&
!conn_info( &axel->conn[0] ) )
{
axel_message( axel, axel->conn[0].message );
axel->ready = -1;
return( axel );
}
s = conn_url( axel->conn );
strcpy( axel->url->text, s );
if( ( axel->proc_param.size = axel->conn[0].size ) != INT_MAX )
{
if( axel->conf->verbose > 0 )
axel_message( axel, _("File size: %i bytes"), axel->proc_param.size );
}
/* Wildcards in URL --> Get complete filename */
if( strchr( axel->filename, '*' ) || strchr( axel->filename, '?' ) )
strcpy( axel->filename, axel->conn[0].file );
// set download parameters
memcpy( axel->ftp_param.host, axel->conn[ 0 ].host, MAX_STRING );
memcpy( axel->ftp_param.username, axel->conn[ 0 ].user, MAX_STRING );
memcpy( axel->ftp_param.password, axel->conn[ 0 ].pass , MAX_STRING );
memcpy( axel->ftp_param.PeerFile, axel->conn[ 0 ].file, MAX_STRING );
memcpy( axel->ftp_param.PeerDir, axel->conn[ 0 ].dir, MAX_STRING );
memcpy( axel->ftp_param.LocalFile, axel->filename , MAX_STRING );
getcwd( axel->ftp_param.LocalDir, MAX_STRING );
axel->ftp_param.Port = axel->conn[ 0 ].port;
axel->ftp_param.PassiveMode = 1;
axel->ftp_param.BinaryMode = 1;
if( axel->direct == DOWNLOAD )
axel->ftp_param.DownLoad = 1;
else
axel->ftp_param.DownLoad = 0;
axel->file_id = file_id;
// conn_disconnect( &axel->conn[ 0 ] );
return( axel );
}
/* Open a local file to store the downloaded data */
int axel_open( axel_t **ref_axel )
{
int i, fd;
axel_t *axel = *ref_axel;
if( axel->conf->verbose > 0 )
axel_message( axel, _("Opening output file %s"), axel->filename );
snprintf( buffer, MAX_STRING, "%s.st", axel->filename );
axel->outfd = -1;
/* Check whether server knows about RESTart and switch back to
single connection download if necessary */
if( axel->direct == DOWNLOAD )
{
if( !axel->conn[0].supported )
{
axel_message( axel, _("Server unsupported, "
"starting from scratch with one connection.") );
axel->conf->num_connections = 1;
axel->conn = realloc( axel->conn, sizeof( conn_t ) );
axel->status->mask = 1;
axel_divide( axel );
axel->conn[ 0 ].file_id = axel->file_id;
}
else if( ( fd = open( buffer, O_RDONLY ) ) != -1 )
{
read( fd, &axel->conf->num_connections, sizeof( axel->conf->num_connections ) );
axel->conn = realloc( axel->conn, sizeof( conn_t ) * axel->conf->num_connections );
memset( axel->conn + 1, 0, sizeof( conn_t ) * ( axel->conf->num_connections - 1 ) );
axel_divide( axel );
read( fd, &axel->proc_param.bytes_done, sizeof( axel->proc_param.bytes_done ) );
for( i = 0; i < axel->conf->num_connections; i ++ )
{
read( fd, &axel->conn[i].currentbyte, sizeof( axel->conn[i].currentbyte ) );
axel->conn[ i ].proc_param.start_byte = axel->conn[ i ].currentbyte;
}
axel_message( axel, _("State file found: %i bytes downloaded, %i to go."),
评论26
最新资源