在仔细阅读代码之前,需要先研究一下Axel的数据结构。
- typedef struct
- {
- conn_t *conn;
- conf_t conf[1];
- char filename[MAX_STRING];
- double start_time;
- int next_state, finish_time;
- long long bytes_done, start_byte, size;
- int bytes_per_second;
- int delay_time;
- int outfd;
- int ready;
- message_t *message;
- url_t *url;
- } axel_t;
首先是axel_t,显然,这是一个对每一个任务创建的结构体,包括了conn_t结构体,conf结构体,文件名,大小,速度,延迟,url等等,注意到前两个结构体我们还不知道是什么呢。。。。好吧,那就看看吧。。。
- typedef struct
- {
- conf_t *conf;
-
- int proto;
- int port;
- int proxy;
- char host[MAX_STRING];
- char dir[MAX_STRING];
- char file[MAX_STRING];
- char user[MAX_STRING];
- char pass[MAX_STRING];
-
- ftp_t ftp[1];
- http_t http[1];
- long long int size; /* File size, not 'connection size'.. */
- long long int currentbyte;
- long long int lastbyte;
- int fd;
- int enabled;
- int supported;
- int last_transfer;
- char *message;
- char *local_if;
- int state;
- pthread_t setup_thread[1];
- } conn_t;
根据名称猜测,这是有关下载任务的连接的属性,通过这个结构体来建立TCP连接及上层的FTP、HTTP连接,因为Axel是多线程的,所以还包括了pthread_t ,通过名字我猜这个setup_thread是在建立连接的时候有用到,因为暂时还没看到,所以先不管。
接下来,是conf_t:
- typedef struct
- {
- char default_filename[MAX_STRING];
- char http_proxy[MAX_STRING];
- char no_proxy[MAX_STRING];
- int strip_cgi_parameters;
- int save_state_interval;
- int connection_timeout;
- int reconnect_delay;
- int num_connections;
- int buffer_size;
- int max_speed;
- int verbose;
- int alternate_output;
-
- if_t *interfaces;
-
- int search_timeout;
- int search_threads;
- int search_amount;
- int search_top;
- int add_header_count;
- char add_header[MAX_ADD_HEADERS][MAX_STRING];
-
- char user_agent[MAX_STRING];
- } conf_t;
真是一个比一个长了,不过都长不到哪里去。可以看到里面有最大速度、buffer大小、有木有代理等等配置信息。以后看到的时候再来一个一个分析吧。。。
Good,三个接下来涉及到的数据结构都看到了,我们接下来分析一下新建任务的函数。
- axel_t *axel_new( conf_t *conf, int count, void *url )
- {
- search_t *res;
- axel_t *axel;
- url_t *u;
- char *s;
- int i;
-
- 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,进行相关的初始化,包括缓存大小、最大速率等,因为我刚开始看,暂时对这些初始化的用处还不太了解,不过可以先从名字猜到一些的。
继续往下看:
- if( count == 0 )
- {
- axel->url = malloc( sizeof( url_t ) );
- axel->url->next = axel->url;
- strncpy( axel->url->text, (char *) url, MAX_STRING );
- }
- else
- {
- res = (search_t *) url;
- u = axel->url = malloc( sizeof( url_t ) );
- for( i = 0; i < count; i ++ )
- {
- strncpy( u->text, res[i].url, MAX_STRING );
- if( i < count - 1 )
- {
- u->next = malloc( sizeof( url_t ) );
- u = u->next;
- }
- else
- {
- u->next = axel->url;
- }
- }
- }
这段代码是把一系列的URL放到任务里面,url_t这个数据类型实际上是一个链表,之所以存放不止一个Url是因为服务器有多个镜像的原因。
接下来~
- axel->conn[0].conf = axel->conf;
- if( !conn_set( &axel->conn[0], axel->url->text ) )
- {
- axel_message( axel, _("Could not parse URL.\n") );
- axel->ready = -1;
- return( axel );
- }
- axel->conn[0].local_if = axel->conf->interfaces->text;
- axel->conf->interfaces = axel->conf->interfaces->next;
-
- strncpy( axel->filename, axel->conn[0].file, MAX_STRING );
- http_decode( axel->filename );
- if( *axel->filename == 0 ) /* Index page == no fn */
- strncpy( axel->filename, axel->conf->default_filename, MAX_STRING );
- 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 );
- }
这段代码,第一行初始化配置,然后是解析Url(conn_set这个函数),根据结果初始化axel里面的一个从conn_t类型的成员变量。接下来初始化interface,这个暂时先搁着,后面会说到。接着解析文件名,进行conn_init即初始化conn_t的一个变量。
- /* This does more than just checking the file size, it all depends
- on the protocol used. */
- if( !conn_info( &axel->conn[0] ) )
- {
- axel_message( axel, axel->conn[0].message );
- axel->ready = -1;
- return( axel );
- }
- s = conn_url( axel->conn );
- strncpy( axel->url->text, s, MAX_STRING );
- if( ( axel->size = axel->conn[0].size ) != INT_MAX )
- {
- if( axel->conf->verbose > 0 )
- axel_message( axel, _("File size: %lld bytes"), axel->size );
- }
-
- /* Wildcards in URL --> Get complete filename */
- if( strchr( axel->filename, '*' ) || strchr( axel->filename, '?' ) )
- strncpy( axel->filename, axel->conn[0].file, MAX_STRING );
-
- return( axel );
- }
这一段有注释(怎么就这一段有。。。),就偷点懒。。不说了。。。呵呵
新建任务就说到这里了,肯定有很多说的不对,等大神来指点指点。
阅读(938) | 评论(0) | 转发(0) |