QUIC探索(二):编译第一个QUIC工程

前言

前篇文章简单介绍了QUIC协议在业内存在的几种开源实现,但是归根结底主要可以分为Google开源的chromium库自带的QUIC实现方案,还有利用Go语言来重写的QUIC协议实现库。
相对来说,更加建议在chromium上面进行QUIC的研究,从多平台支持、功能的稳定性都有一定的保证,当然chromium浩大繁杂的源码库也是明显拔高了QUIC学习的入门难度。

获取源码

其实对于编译chromium的衍生工程来说,基本上流程都是差不多的,类似的可以参考《Webrtc 研究: Android编译》这篇文章。
限于篇幅,这里就以获取Linux环境下的chromium源码库的步骤进行介绍,对于Android、iOS的介绍后续有空再补上。

安装编译依赖环境

depot_tools是chromium编译必须依赖的编译环境,安装的方式很简单,只要git clone这个depot_tools库到本地即可。

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

需要将depot_tools安装目录添加到环境变量里面。

export PATH=$PATH:/path/depot_tools

其实也可以直接将路径配置到启动脚本里面,这样就不用每次启动终端就重新export一次好累人。

拉取chromium源码

准备好环境了就可以开始拉取chromium源码了。
创建一个存放源码的目录,当然文件名可以看自己心情。

mkdir ~/chromium
cd ~/chromium

检出源码,然后静静得喝杯茶等待吧~

fetch -nohooks chromium

PS:如果仅仅只是想编译最新版本源码的话,可以添加--no-history能减少一些下载量,但是缺点就是无法切换到旧版本源码。

安装构建所需的依赖项

进入源码库的src目录,运行install-build-deps.sh进行编译环境的配置。

cd ~/chromium/src
./build/install-build-deps.sh
gclient runhooks

值得注意的是,对于一个编译环境而言install-build-deps.sh仅需要运行一次即可,其会安装下载一些编译所需要的软件环境。

PS:如果在已经运行过install-build-deps.sh的机器重新检出chromium源码的话,可以不输入-nohooks这个选项,其会在fetch完毕后自动gclient runhooks。

编译第一个QUIC项目

编译quic-sever和quic-client工程

生成编译参数配置脚本文件。

gn args out/Default

这时候一般会新建一个文件out/Default/args.gn,并进入文本编辑模式;如果不需要特殊配置编译参数的话,直接保存退出即可。
接下来编译系统会根据args.gn的配置自动生成ninja文件。

如果后续需要修改编译参数的话,编辑args.gn文件后,执行

gn gen out/Default

就可以重新生成ninja文件。

接下来可以开始编译quic_server和quic_client模块。

ninja -C out/Debug quic_server quic_client

等待编译完成,进入out/Default下可以看到quic_server和quic_client可执行文件。

运行quic-sever和quic-client工程

在运行工程前,我们需要先准备测试数据。

mkdir /tmp/quic-data
cd /tmp/quic-data
wget -p --save-headers https://www.example.org

修改测试数据如下

cd www.example.org/
vim index.html

index.html按照下面的提示进行修改

HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Fri, 14 Jun 2019 06:19:23 GMT
Etag: "1541025663"
Expires: Fri, 21 Jun 2019 06:19:23 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (oxr/830F)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270
#添加这一行
X-Original-Url: https://www.example.org/

#将后面内容全部删除,改成你想要测试的数据,例如改成json数据
{"code":200,"name":"quic"}

我们需要生成一个加密证书,这是因为这个DEMO包含了SSL加密的逻辑。

cd /<chromium-path>/src/net/tools/quic/certs/
./generate-certs.sh

将证书部署到系统

apt install libnss3-tools
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n quic -i /<chromium-path>/src/net/tools/quic/certs/out/2048-sha256-root.pem
#查看证书是否添加成功
certutil -d sql:$HOME/.pki/nssdb -L
#用完可以删除证书
certutil -d sql:$HOME/.pki/nssdb -D -n quic

如果证书没有添加成功,那么运行客户端会出现这个错误。

[0614/004201.673072:ERROR:cert_verify_proc_nss.cc(981)] CERT_PKIXVerifyCert for www.example.org failed err=-8179
[0614/004201.674716:WARNING:proof_verifier_chromium.cc(502)] Failed to verify certificate chain: net::ERR_CERT_AUTHORITY_INVALID
Failed to connect to 127.0.0.1:12306. Error: QUIC_PROOF_INVALID

运行server服务器,监听本地12306端口。

cd /<chromium-path>/src
./out/Default/quic_server \
    --quic_response_cache_dir=/tmp/quic-data/www.example.org \
    --certificate_file=net/tools/quic/certs/out/leaf_cert.pem \
    --key_file=net/tools/quic/certs/out/leaf_cert.pkcs8 \
    --host=127.0.0.1 \
    --port=12306

运行quic-client客户端,向本地12306端口发送请求,顺便提一句如果没指定端口的话会默认采用80端口。

cd /<chromium-path>/src
./out/Default/quic_client  \
    --host=127.0.0.1 \
    --port=12306 \
    https://www.example.org/

如果想输出更详细的调试信息,可以加上--v=1

下面是运行结果的信息输出

Connected to 127.0.0.1:12306
Request:
headers:
{
  :method GET
  :scheme https
  :authority www.example.org
  :path /
}
body:

Response:
headers:
{
  :status 200
  accept-ranges bytes
  cache-control max-age=604800
  content-type text/html; charset=UTF-8
  date Fri, 14 Jun 2019 06:19:23 GMT
  etag "1541025663"
  expires Fri, 21 Jun 2019 06:19:23 GMT
  last-modified Fri, 09 Aug 2013 23:54:35 GMT
  server ECS (oxr/830F)
  vary Accept-Encoding
  x-cache HIT
  content-length 1270
  x-original-url https://www.example.org/
}

body: {"test":"quic","code":400}

trailers: {}
Request succeeded (200).

编译运行quartc-test工程

如果不想运行基于HTTP封装的QUIC协议,而想测试模拟SOCKET的QUIC数据接发,可以测试一下Quartc相关的测试用例。
PS:Quartc并不需要配置SSL加密证书。
这个模块基于gtest,当然这里并不需要了解那么多。

首先,先编译quartc-test测试模块,由于quartc-test的代码包含在net_unittests这个net模块测试用例集里面

#编译net测试用例集合
ninja -C out/Default/ net_unittests

接下来就可以运行quartc的测试工程

#quic流握手测试用例
./out/Default/net_unittests --single-process-tests --gtest_filter=QuartcSessionTest.StreamConnection
#quic流关闭测试用例
./out/Default/net_unittests --single-process-tests --gtest_filter=QuartcSessionTest.CloseQuartcStream
#quic流数据发送测试用例
./out/Default/net_unittests --single-process-tests --gtest_filter=QuartcSessionTest.BundleWrites

这个是运行QuartcSessionTest.BundleWrites这个测试用例的结果输出

Note: Google Test filter = QuartcSessionTest.BundleWrites
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from QuartcSessionTest
[ RUN      ] QuartcSessionTest.BundleWrites
[59022:59022:0614/032154.391161:53217086974:INFO:quartc_session_test.cc(337)] Crypto handshake complete!
[59022:59022:0614/032154.391991:53217087794:INFO:quartc_session_test.cc(337)] Crypto handshake complete!
[       OK ] QuartcSessionTest.BundleWrites (16 ms)
[----------] 1 test from QuartcSessionTest (16 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (19 ms total)
[  PASSED  ] 1 test.

可以参考测试源码进行相对应调试和日志输出,这块后续会有文章介绍。

chromium的net模块

如果我们想要使用chromium里面的QUIC相关功能,最佳的方案就是选择编译chromium的net模块。
至少我们可以知道net模块提供的功能在chromium所有支持的平台上都是经过稳定性测试的,换句话说我们可以通过net在各个平台上面达到使用QUIC协议的目的。
可能你们会说net模块的编译出来的动态库会有点大,一种方案就是用编译脚本进行功能裁剪,另外一种方案就是修改GN脚本进行代码抽离,这个后面有空再解释。

选择QUIC的历史版本

由于quic-go、Caddy、谷歌浏览器等并不能同步支持到QUIC的最新版本,所以建议在一个稳定的版本进行QUIC开发更加靠谱。
现在市面上主流支持是quic44、quic43、quic39之类的,我用shareshark抓包发现其只支持到quic43,所以后续是以quic43展开研究的。

如果要用以前版本的QUIC版本,可以在同步版本时这么指定

#注意这里不能用--no-history
fetch --nohooks chromium
cd src
#切换到你想要的版本,这里是68.0.3440.134
git fetch origin 68.0.3440.134
git checkout -b my_stable_branch FETCH_HEAD
gclient sync --with_branch_heads

build/install-build-deps.sh
gclient runhooks
gn args out/Default
ninja -C out/Default net

这里你会疑惑68.0.3440.134是什么鬼,这是是chromium的版本号,其各个数字的意义如下:

  • 68.0 - 为chrome主版本号,通常它的变化频率很低,通常当它有所变化就意味着chrome本身有了较多的改进。
  • 3440 - 它是当前版本的代号,每当它有所增大,就意味着Chrome有新功能出现或者是某些原有功能得到改进。
  • 134 - 这个数字代表Chrome在安全性和稳定性方面的更新,它的增加不会带来新功能,仅仅是修补漏洞和改善稳定性。

注意注意敲黑板,QUIC版本号并不跟chromium版本号同步,那么怎么通过chromium的版本号来获得QUIC的版本呢?
那么可以通过这个在线源码网站
https://chromium.googlesource.com/chromium/src.git 中查看 net/third_party/quic/core/quic_versions.cc 这个文件就能清楚看出当前的QUIC版本,例如:

QuicString QuicVersionToString(QuicTransportVersion transport_version) {
  switch (transport_version) {
    RETURN_STRING_LITERAL(QUIC_VERSION_35);
    RETURN_STRING_LITERAL(QUIC_VERSION_37);
    RETURN_STRING_LITERAL(QUIC_VERSION_38);
    RETURN_STRING_LITERAL(QUIC_VERSION_39);
    RETURN_STRING_LITERAL(QUIC_VERSION_41);
    RETURN_STRING_LITERAL(QUIC_VERSION_42);
    //当前的QUIC版本为43
    RETURN_STRING_LITERAL(QUIC_VERSION_43);
    //99并不是一个版本号,而已预留给后续的升级兼容对接
    RETURN_STRING_LITERAL(QUIC_VERSION_99);
    default:
      return "QUIC_VERSION_UNSUPPORTED";
  }
}

结语

这篇文章简单介绍了怎么拉取chromium源码并且编译出适用于Linux环境的QUIC工程,以及其过程中的注意事项,后续会从源码层面介绍怎么进行QUIC的定制开发。

本文发布于 简书

End!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345