Aria2源代码分析——aria2 1.19.2

原创 2015年11月20日 16:46:43
Aria2源代码分析-aria2.1.19.2

1.src/main.cc
主程序入口,从命令行接受启动参数,判断系统类型,调用不同的context构造函数

2.context类/结构
Context(bool standalone, int argc, char** argv, const KeyVals& options);
standalone /*没搞懂这个变量的意义,但是目测在openwrt下就是true,不需要特意关注*/
KeyVals& options /*KeyVals是一个自定义指针,类似于字典的格式,对组.
 The type of Key/Value pairs.*/
typedef std::vector<std::pair<std::string, std::string> > KeyVals;

3.context构造函数实现,首先调用option_processing函数,基本就是解析启动参数,不用关注细节。
之后根据协议类型调用,判断是BT 是url 还是磁力链接
只分析BT 输入参数为 本地目录torrent文件,非URL,如此则调用createRequestGroupForBitTorrent

4.createRequestGroupForBitTorrent
/*这个做了一个重构函数,针对输入的是url的torrent地址或者是xxx.torrent文件,总之最终都转化为种子文件名*/
但是adjustAnnounceUri没有传值???之后又继续作为参数往下传递了??
之后调用createBtRequestGroup

5.createBtRequestGroup
/*adjustAnnounceUri在此函数中作为入参直接赋值为true,不清楚原因*/
auto rg = std::make_shared<RequestGroup>(gid, option);
auto dctx = std::make_shared<DownloadContext>();
/*这里创建了两个类指针,从而调用其构造函数*/
5.1 RequestGroup
构造函数初始化了一些下载用的参数,调用了两个初始化函数,继续深入……
initializePreDownloadHandler();
initializePostDownloadHandler();
/* 初始化下载句柄。。获取了BT下载的句柄*/
getBtPreDownloadHandler,getBtPostDownloadHandler
5.2 DownloadContext
设定一些下载参数,看命名应该是比如,文件大小,分片之类的

6.main.cc 之前遗漏。。,程序最重要的执行入口。。。
  if(context.reqinfo) {
    exitStatus = context.reqinfo->execute();
  }
  std::shared_ptr<MultiUrlRequestInfo> reqinfo;
/*因此首先调用MultiUrlRequestInfo中的 excute*/

7.error_code::Value MultiUrlRequestInfo::execute()
     try {
    e_->run();
  } catch(RecoverableException& e) 
  这里, e_是 std::unique_ptr<DownloadEngine> e_;
  所以接下来调用DownloadEngine中的 run

8.int DownloadEngine::run(bool oneshot)
    /*此cc中 run()->excuteCommand()->excute()
    这里的excute我觉得是 bool AbstractCommand::execute()
    此处是父类(抽象类?)的excute,根据命令的类型,去判断触发哪种下载模式的excute()???猜测
    这里用到了getDownloadEngine
    之前的一系列构造函数调用和初始化中,有调用到其对应的set宏*/

    /*AbstractCommand::execute(),基类的excute,其余所有子类继承之*/  

9.bool AbstractCommand::execute()
    这里是下载真正执行的地方:
    e_->poolSocket(req_, createProxyRequest(), socket_);
    DownLoadEngine poolSocket()此函数为下载 socket 线程池??重构四个形态
    SocketPoolEntry e(sock, std::move(timeout));
  poolSocket(createSockPoolKey(ipaddr, port, A2STR::NIL,proxyhost,proxyport),e);

10.纠正8中的excute问题, 原调用形式如下:
for(size_t i = 0; i < max; ++i) {
    auto com = std::move(commands.front());
    commands.pop_front();
    if (!com->statusMatch(statusFilter)) {
      com->clearIOEvents();
      commands.push_back(std::move(com));
      continue;
    }
    com->transitStatus();
    if (com->execute()) {
      com.reset();
    }
    else {
      com->clearIOEvents();
      com.release();
    }
  }
/*com是自动类型,因此这里调用的excute具体是哪个类中的excute完全看获取到的command,所以既可能是调用
基类AbstractCommand中的excute,也可能是bool FillRequestGroupCommand::execute()
纠正错误。AbstractCommand并非基类。。基类是Command。。。AbstractCommand DownLoadCommand 
FillRequestGroupCommand等等全是Command的子类*/

11.纠正前面的错误。。。。  AbstractCommand。。这个这个,应该列出一个从Command开始的类继承关系图。。
然而种类太多了。。。一一列举不能
那么关注此子类     PeerAbstractCommand
它的子类   PeerInitiateConnectionCommand
bool PeerInitiateConnectionCommand::executeInternal() {
  A2_LOG_INFO(fmt(MSG_CONNECTING_TO_SERVER,
                  getCuid(),
                  getPeer()->getIPAddress().c_str(),
                  getPeer()->getPort()));
  createSocket();
  getSocket()->establishConnection(getPeer()->getIPAddress(),
                                   getPeer()->getPort(), false);
这里创建了socket连接。。。    

12.继续探究Command基类的子类,发现TrackerWatcherCommand这个类应当是BT下载的实现
它的excute中 
if(!trackerRequest_) {
    trackerRequest_ = createAnnounce(e_);//此处是创建一个客户端宣告信息,貌似

下面看上去是轮询所有的tracker信息,每个tracker服务器都尝试去连接。。  
那么问题来了。。。种子解析在哪。。。

13.种子解析在之前提到过的context构造函数中……好吧,搞清楚了。。
#ifdef ENABLE_BITTORRENT
  if(!op->blank(PREF_TORRENT_FILE)) {
    if(op->get(PREF_SHOW_FILES) == A2_V_TRUE) {
      showTorrentFile(op->get(PREF_TORRENT_FILE));
      return;
    } else {
      createRequestGroupForBitTorrent(requestGroups, op, args,
                                      op->get(PREF_TORRENT_FILE));
    }
  }
/*是的。。就是这一段,blank是判断传进的字符串是否为空,这里的话就是判断你给没给torrent文件吧。。
op->get 是取那个参数的值。。那些宏都是Prefer指针。。有的是数字,有的是字符串,有的是true or false
详细的见Prefers.cc  就是属性(preferance)定义。。看文件的大概意思,应该是把这些不同的值,都归类为Pref指针
然后搞了一个数组把它们都串起来,抽象为一个id,或者一个key值。。你调用的aria2的时候应该给的就是关键字或者
id,然后程序自动转换成其所代表的意义。。。。大概是这样*/

/*言归正传,这里先判断了是否提供了torrent文件,之后判断你要做的是什么操作。。如果是show-file操作,
那么解析这个种子文件并且返回种子文件的内容。。什么uri啦。。announce啦。。等等,都给你打印在屏幕上吧
如果不是show-file,那么就创建RequestGroup了,在这里就有种子文件的解析。。*/
show-file分支,解析调用的是bittorrent::load()
createRequestGroup分支,调用的是 bittorent::LoadFromMemory()
他们都定义在 bittorent_helper.cc
仔细读一下就发现,其实这两个函数都是调用了bittorent::processRootDictionary()这个函数。。
这里就是详细的解析。。然后如果是create的动作,那么相关的信息,存储到 DownloadContext和TorrentAttribute
这两个类

14.到这里我觉得大致的BT下载框架解析完毕。。可以看到aria2用的是udp打洞(具体的可以看NAT穿越)来做P2P通信,
并没有用现成的bittorrent库之类的,但是基本思想是照抄的,即 client-tracker-client模式

15.如果还需要深入研究各种功能。。最好的办法我觉得是 从Command这一基类,找到它的子类。。挨个分析,树状遍历       
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

aria2配置示例

 aria2配置示例 其实面对man的存在,写什么总结完全没有必要,一切宝藏都在manual。不过反正不会有人会读就是了。那我就写一下吧 ##基础 首先,aria2或者叫做aria2c...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

树莓派变身Aria2下载服务器

入手树莓派有一段时间了,这小东西还是很好玩的,这几天研究了一下,把它做成了一个下载服务器~和大家分享一下。 主要用到的程序是Aria2 + Yaaw, Aria2这是一个支持Http、FTP、磁力链...

利用Aria2和旧电脑打造一台下载机

利用这个下载神器—— Aria2,可以把你的旧电脑 / 手机变成一台免费的(电费除外)的 24 小时运行的下载机,比那些所谓的“离线下载”好多了 Aria2是全平台的,Windows、MAC、Lin...

Aria2 使用手札

这是感觉写的比较好的一篇博客了,收藏了 http://www.cnblogs.com/RhinoC/p/aria2.html# Aria2 使用手札(简易部署 + 快速进阶) 没错,又是受够了迅雷、...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Debian 8.0 系统安装

[1] Insert a disk for installation of Debian 8 Jessie and reboot your computer. Next, select install...

Debian服务器下SSH的配置与问题

参考http://www.howtoforge.com/set-up-ssh-with-public-key-authentication-debian-etch 服务器端 1.在服务器端安装ssh ...
  • zfpnuc
  • zfpnuc
  • 2011年06月26日 19:54
  • 11440

Aria2 1.3.3 PC

  • 2017年11月07日 19:02
  • 28.42MB
  • 下载

aria2-1.27.1-win-64bit-build1(已配置版)

  • 2017年08月11日 14:50
  • 1.95MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Aria2源代码分析——aria2 1.19.2
举报原因:
原因补充:

(最多只允许输入30个字)