引言

BitTorrent(BT)是一种基于P2P的通信协议,提供了一种非中心化的数据、文件共享方式。那P2P节点相互如何发现呢?最简单的做法就是建议一个中心化的服务器(Tracker),来接收各个节点的上报,比如我需要下载哪个文件,我拥有哪些文件。这样就有了我们熟悉的种子torrent文件,帮助我们和Tracker通信。Ocelot是国外某著名音乐站点Tracker的开源项目,借助于此项目可以从代码层面学习和认识Tracker。

PT站架构

Ocelot 编译及运行

笔者的系统环境为Ubuntu 16,根据安装文档,我们简化一下安装Ocelot需要的依赖为:

1
2
sudo apt install mysql-server mysql-client libmysql++-dev libmysqld-dev \
libev-dev git cmake libbz2-dev libtcmalloc-minimal4 libboost-all-dev

安装完mysql后初始化root密码,新建table如gazelle.sql,考虑对该文件做如下修改

1
2
3
4
5
6
7
8
9
SET FOREIGN_KEY_CHECKS = 0;
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

DROP DATABASE IF EXISTS gazelle;

CREATE DATABASE gazelle CHARACTER SET utf8 COLLATE utf8_swedish_ci;

USE gazelle;
//...

上述修改去掉了sql_mode配置的_STRICT_TRANS_TABLES_, _NO_ZERO_DATE_,前者会导致insert into for update强制校验不允许default值的字段,后者会导致gazelle.sql中日期默认值如_0000-00-00 00:00:00_失败。

修改项目中config.cpp文件的mysql登陆用户名及密码:

1
2
	add("mysql_username", "root");
	add("mysql_password", "xxxx");

笔者使用的C++ IDE为Clion,打开Ocelot工作目录,编写cmake编译配置文件CMakeLists.txt如

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
cmake_minimum_required(VERSION 3.19)
project(Ocelot)

set(CMAKE_CXX_STANDARD 14)

include_directories(. /usr/include/mysql/)
link_directories(/usr/lib/x86_64-linux-gnu/)

add_executable(Ocelot
        config.cpp
        config.h
        db.cpp
        db.h
        events.cpp
        events.h
        misc_functions.cpp
        misc_functions.h
        ocelot.cpp
        ocelot.h
        report.cpp
        report.h
        response.cpp
        response.h
        schedule.cpp
        schedule.h
        site_comm.cpp
        site_comm.h
        user.cpp
        user.h
        worker.cpp
        worker.h)

target_link_libraries(Ocelot
        ev
        mysqlpp
        pthread
        boost_system
        boost_iostreams)

这样,项目就可以启动了,运行后会看到控制台输出:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Using default config because './ocelot.conf' couldn't be opened
Start Ocelot with -c <path> to specify config file if necessary
Clearing xbt_files_users and resetting peer counts...done
Loaded 1 users
Loaded 1 torrents
Loaded 0 tokens
Assuming no whitelist desired, disabling
Sockets up on port 34000, starting event loop!
0 open, 0 connections (0/s), 0 requests (0/s)
0 open, 0 connections (0/s), 0 requests (0/s)
0 open, 0 connections (0/s), 0 requests (0/s)
...

测试

通过抓包发现,BT客户端Announce请求如

1
curl -H 'Host: 127.0.0.1' -H 'User-Agent: qBittorrent/4.3.2' --compressed 'http://127.0.0.1:3400/[32位passkey]/announce?info_hash=[40位种子pass_hash]&peer_id=[20位peer_id]&port=32779&uploaded=10984485&downloaded=270144869&left=0&corrupt=0&key=82D19544&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0'

参照上面的请求,在mysql中插入2条数据:

1
2
3
4
5
6
insert into users_main 
	(`Username`, `IP`, `Enabled`,`torrent_pass`, `Email`, `PassHash`, `Secret`, `Title`, `PermissionID`) 
	values ('xxx', '127.0.0.1', 1,'[32位passkey]', '', '', '', '',0); 
insert into torrents
	(`GroupID`, `info_hash`, ...)
	values('0', '[40位种子pass_hash]', ...)

重启Ocelot,发送上面的curl请求。发现torrents,xbt_files_users有数据更新,初步测试通过。愉快地调试代码吧!

未完待续

[ev处理流程,BT协议及编码]


版权所有,转载请注明来源