chromium网络栈学习

本文详述Chromium的网络栈,涵盖SSL/TLS的常识及浏览器中的SSL版本选择,HTTP协议、缓存机制,重点解析HttpCache::Transaction的执行流程,包括DoLoop中的各个步骤,以及QUIC和Spdy协议的基础知识。此外,还涉及网络工具的使用、WebSocket与Push Notifications等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内容目录

1 Overview 3

1.1 常用工具 6

1.2 SSL,TLS 6

1.2.1 常识 6

1.2.2 browser代码中ssl版本的选择以及握手的过程 7

1.3 额外需要细节性分析的部分: 20

1.4 http 协议 20

1.4.1 http authencation 20

1.4.1.1 basic authentication 20

1.4.1.2 Digest access authentication 21

1.4.2 http cache 23

1.5 blinkhttpcache模块分析 24

1.6 http_cache_transactiondoloop详细步骤: 30

1.7 http_cache_transactiondoloopbackend的建立 34

1.8 http_cache_transactioninit/openentry 38

1.9 Create entry 39

1.10 Add transaction to entry 39

1.11 send request 39

1.11.1为了执行HttpCache::Transaction::SendRequest,在HttpNetworkTransactionDoLoop里执行该任务。HttpNetworkTransaction有自己的Doloop. 40

1.11.1.1 HttpNetworkTransaction::DoCreateStream 43

1.11.1.1.1HttpStreamFactoryImpl::Job::Runloop,完成stream的建立工作,ssl握手等 44

1.11.1.2 HttpNetworkTransaction::DoCreateStreamComplete. 56

1.11.1.3 HttpNetworkTransaction::DoInitStream 56

1.11.1.4 int HttpNetworkTransaction::DoInitStreamComplete 57

1.11.1.5 int HttpNetworkTransaction::DoGenerateProxyAuthToken() { 57

1.11.1.6 HttpNetworkTransaction::DoGenerateProxyAuthTokenComplete(intrv) 57

1.11.1.7 int HttpNetworkTransaction::DoGenerateServerAuthToken() { 58

1.11.1.8HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) 58

1.11.1.9 int HttpNetworkTransaction::DoInitRequestBody() 58

1.11.1.10 int HttpNetworkTransaction::DoInitRequestBodyComplete(intresult) { 58

1.11.1.11 int HttpNetworkTransaction::DoBuildRequest() 58

1.11.1.12 HttpNetworkTransaction::DoBuildRequestComplete 59

1.11.1.13HttpNetworkTransaction::DoSendRequest(callback还是HttpNetworkTransaction::OnIOComplete) 59

1.11.1.13.1 HttpStreamParser::DoSendHeaders 61

1.11.1.13.2 int HttpStreamParser::DoSendHeadersComplete(intresult) 61

1.11.1.13.3 HttpStreamParser::DoSendBody //如果没有body就不会走到这里 61

1.11.1.14 int HttpNetworkTransaction::DoSendRequestComplete(intresult) 66

1.11.1.15 HttpNetworkTransaction::DoReadHeaders 66

1.11.1.15.1 HttpStreamParser::DoReadHeaders 67

1.11.1.15.2 int HttpStreamParser::DoReadHeadersComplete(intresult) 69

1.12 HttpCache::Transaction::DoSendRequestComplete(int result) 70

1.13 HttpCache::Transaction::DoSuccessfulSendRequest() 70

1.14 HttpCache::Transaction::DoOverwriteCachedResponse 75

1.15 HttpCache::Transaction::DoCacheWriteResponse 75

1.16 HttpCache::Transaction::DoCacheWriteResponseComplete 77

1.17 HttpCache::Transaction::DoTruncateCachedData 77

1.18 HttpCache::Transaction::DoTruncateCachedDataComplete 77

1.19 HttpCache::Transaction::DoTruncateCachedDataComplete 77

1.20 HttpCache::Transaction::DoTruncateCachedMetadata 77

1.21 HttpCache::Transaction::DoTruncateCachedMetadataComplete 77

1.22 HttpCache::Transaction::DoPartialHeadersReceived 77

1.23 下面是读取body的逻辑,从header接受完毕,到开始触发body读取,经过了从底层socket向上通知,一致到达ResourceLoader的层面,由ResourceLoader触发Read操作。 78

1.24 HttpCache::Transaction::DoNetworkRead 82

1.24.1 HttpNetworkTransaction::Read 83

1.24.2 HttpNetworkTransaction::DoReadBody 83

1.24.2.1 HttpBasicStream::ReadResponseBody 83

1.24.3 HttpNetworkTransaction::DoReadBodyComplete(int result) 84

1.25 HttpCache::Transaction::DoNetworkReadComplete 84

1.26 HttpCache::Transaction::DoCacheWriteData 84

1.27 HttpCache::Transaction::DoCacheWriteDataComplete 84

1.28 得到数据之后的处理 91

2 Metadata的保存 91

3 QUIC 93

3.1 一些quic的基本点 94

3.1.1 链接的建立 95

3.1.2 ClientIp地址,port如果变化如何通知servier 95

3.1.3 加密相关 95

3.1.4 一些potocol细节 95

3.1.5 Framing 96

3.1.6 Quic的加密 96

4 Spdy 96

4.1 overview 96

4.2 Protocol specification 97

4.2.1 Connection 98

4.2.2 Framing 98

4.2.3 Streams 98

4.2.3.1 Stream的创建。 98

4.2.3.2 Stream data exchange 99

4.2.3.3 Stream close 99

5 Push Notifications 99


1 Overview

http://dev.chromium.org/developers/design-documents/network-stack



Single threaded,

异步操作,不许block.异步的通知,completioncallback

主接口就是URLRequest,URLRequestCOntext

cookie的管理和使用。CookieMonster

https://tools.ietf.org/html/draft-ietf-httpstate-cookie-23





Httppipelineing

http://en.wikipedia.org/wiki/HTTP_pipelining





httpauthentication.

http://dev.chromium.org/developers/design-documents/http-authentication

proxy

proxyService,proxyResolver, PAC 脚本

SOCKSTUNNEL



SPDY

SPDYis an experiment with protocols for the web.  Its goal is toreduce the latency of web pages.

http://www.chromium.org/spdy/

spdy将要被google抛弃。

http2.0



QUIC,UDP

http://dev.chromium.org/quic







socketpool, connection pool



Hostresolution, getaddrinfo(), HostCache,DNS



SSL,libssl, Certificate verification



crypto:

http://dev.chromium.org/developers/design-documents/crypto



HTML5,websocket.

http://www.cnblogs.com/TianFang/archive/2012/04/02/2429954.html

避免采用ajax中的需要发送请求,轮询数据状态的方法。而是在javascript里面就和server建立长链接,可以被动接受数据通知,等。

websocket全双工,也用80端口。

http://en.wikipedia.org/wiki/WebSocket



Pagecache, memory cache,



diskcache: HTTPCache使用diskcache.

android上:http://dev.chromium.org/developers/design-documents/network-stack/disk-cache

android上:http://dev.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend



makethe web faster: 一些性能相关的技术和文章。

https://developers.google.com/speed/?csw=1



1.1 常用工具

抓包tcpdump

http://www.tcpdump.org/tcpdump_man.html

http://www.cnblogs.com/likwo/archive/2012/09/06/2673944.html

http://www.myhack58.com/Article/48/67/2013/39798.htm

tcpdump抓包,然后电脑上用wireshark分析抓包结果。



Fiddler可用于抓http/https

http://www.telerik.com/fiddler

http://blog.csdn.net/zshq280017423/article/details/8928616

fiddler教程:http://kb.cnblogs.com/page/130367/





1.2 SSL,TLS

1.2.1 常识

http://kb.cnblogs.com/page/197396/

http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html



TLS, SSL基于传输层之上,应用层下.

TLS基于SSL上演化来,SSLnetscape的,TLSIETF的,TLSSSL使用起来差不多。但TLS安全性更强。

SSL发展到3.0了。TLS1.0相当于SSL3.1,TLS1.1相当于SSL3.2,TLS1.2相当于SSL3.3

1994 年,NetScape 公司设计了SSL 协议(SecureSockets Layer )的1.0 版,但是未发布。
1995 年,NetScape 公司发布SSL2.0 版,很快发现有严重漏洞。
1996 年,SSL3.0 版问世,得到大规模应用。
1999 年,互联网标准化组织ISOC 接替NetScape 公司,发布了SSL 的升级版 TLS1.0 版。
2006 年和2008 年,TLS 进行了两次升级,分别为TLS1.1 版和TLS1.2 版。最新的变动是2011 TLS1.2 修订版

1.2.2 browser代码中ssl版本的选择以及握手的过程

注意到client断向server发起请求时,在握手阶段,会协商用到的ssl的版本。看一下该代码。

HttpStreamFactoryImpl::Job::Job构造函数中,传入了ssl_config参数用来构造job内部的成员server_ssl_config_,并且server_ssl_config_在下面被修改:

可能在url_request_context_builder.ccbuild函数中,ssl_config_service就是SSLConfigServiceDefaults。它使用默认的ssl设置。



httpNetworkTransaction构造函数中:

session→ssl_config_service()→GetSSLConfig(&server_ssl_config_);//数据来自sessionssl_config_service.

session->GetNextProtos(&server_ssl_config_.next_protos);

proxy_ssl_config_ = server_ssl_config_;



后来...

-HttpStreamFactoryImpl::Job::DoInitConnection

->InitSSLConfig(根据server_ssl_config来修改job对象内部使用的ssl_config数据)



可见如果说ssl版本的设置来自于SSLConfig默认的构造函数中的值:

SSLConfig::SSLConfig()

: rev_checking_enabled(false),

rev_checking_required_local_anchors(false),

version_min(kDefaultSSLVersionMin),

version_max(kDefaultSSLVersionMax),

那么也就是说来自于net::kDefaultSSLVersionMinnet::kDefaultSSLVersionMax.

定义与ssl_config.cc:



const uint16 kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_SSL3;



const uint16 kDefaultSSLVersionMax =

#if defined(USE_OPENSSL)

#if defined(SSL_OP_NO_TLSv1_2)

SSL_PROTOCOL_VERSION_TLS1_2;

#elif defined(SSL_OP_NO_TLSv1_1)

SSL_PROTOCOL_VERSION_TLS1_1;

#else

SSL_PROTOCOL_VERSION_TLS1;

#endif

#else

SSL_PROTOCOL_VERSION_TLS1_2;

#endif



我们是不是仅仅需要把min改成TLS1就可以了?



下面看一下ssl_config中的数值是如何被协商使用的?





ssl_client_socket_pool.cc中:

intSSLConnectJob::DoSSLConnect() {

next_state_ =STATE_SSL_CONNECT_COMPLETE;



ssl_socket_ =client_socket_factory_->CreateSSLClientSocket( //可能创建SSLClientSocketNSS(ssl_client_socket_nss.h)SSLClientSocketOpenSSL(ssl_client_socket_openssl.h),factory应该不一样。实际上经调试,用的factoryDefaultClientSocketFactory(client_socket_factory.cc)

transport_socket_handle_.Pass(),

params_->host_and_port(),

params_->ssl_config(),ssl的配置

context_);

returnssl_socket_->Connect(callback_);

}







callstack:

#0 net::SSLConnectJob::DoSSLConnect(this=this@entry=0x658f5698) at../../net/socket/ssl_client_socket_pool.cc:299 //准备ssl链接。

#1 0x61ebc886 in net::SSLConnectJob::DoLoop(this=this@entry=0x658f5698, result=<optimized out>) at../../net/socket/ssl_client_socket_pool.cc:205

#2 0x61ebc8ae in net::SSLConnectJob::OnIOComplete(this=0x658f5698, result=<optimized out>) at../../net/socket/ssl_client_socket_pool.cc:169

#3 0x61ebb172 in Run (a1=@0x63bff94c: 0, object=<optimizedout>, this=0x63bff930) at ../../base/bind_internal.h:190

#4 MakeItSo (a2=@0x63bff94c: 0, a1=<optimized out>,runnable=...) at ../../base/bind_internal.h:898

#5 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(net::SSLConnectJob::*)(int)>, void (net::SSLConnectJob*, int),void (base::internal::UnretainedWrapper<net::SSLConnect

Job>)>, void (net::SSLConnectJob*,int)>::Run(base::internal::BindStateBase*, int const&)(base=<optimized out>, x2=@0x63bff94c: 0) at../../base/bind_internal.h:1224

#6 0x61eb8520 in Run (a1=@0x63bff94c: 0, this=0x63bff950) at../../base/callback.h:441

#7 net::ClientSocketHandle::OnIOComplete(this=<optimized out>, result=0) at../../net/socket/client_socket_handle.cc:143 //应该是clinetsocket链接完成

#8 0x61eb7d46 in Run (a1=@0x63bff984: 0, object=<optimizedout>, this=0x63bff968) at ../../base/bind_internal.h:190

#9 MakeItSo (a2=@0x63bff984: 0, a1=<optimized out>,runnable=...) at ../../base/bind_internal.h:898

#10 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(net::ClientSocketHandle::*)(int)>, void(net::ClientSocketHandle*, int), void(base::internal::UnretainedWrapper<net::

ClientSocketHandle>)>, void (net::ClientSocketHandle*,int)>::Run(base::internal::BindStateBase*, int const&)(base=<optimized out>, x2=@0x63bff984: 0) at../../base/bind_internal.h:1224

#11 0x61f3ce34 in Run (a1=@0x63bff984: 0, this=0x63bff98c) at../../base/callback.h:441

#12 net::internal::ClientSocketPoolBaseHelper::InvokeUserCallback(this=0x64245410, handle=<optimized out>) at../../net/socket/client_socket_pool_base.cc:1133

#13 0x61f3e0c8 in Run (a1=@0x65b52fb0: 0x5fbcc920,object=<optimized out>, this=0x63bffa50) at../../base/bind_internal.h:190

#14 MakeItSo (a2=@0x65b52fb0: 0x5fbcc920, weak_ptr=...,runnable=...) at ../../base/bind_internal.h:909

#15 base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void(net::internal::ClientSocketPoolBaseHelper::*)(net::ClientSocketHandle*)>,void (net::internal::ClientSocketPoolBaseHel

per*, net::ClientSocketHandle*), void(base::WeakPtr<net::internal::ClientSocketPoolBaseHelper>,net::ClientSocketHandle*)>, void(net::internal::ClientSocketPoolBaseHelper*,net::ClientSocketHandle*)>::Run(base::

internal::BindStateBase*) (base=0x65b52f98) at../../base/bind_internal.h:1253

#16 0x61cbbb5c in Run (this=0x63bffb60) at../../base/callback.h:401

#17 base::MessageLoop::RunTask (this=this@entry=0x62b81250,pending_task=...) at ../../base/message_loop/message_loop.cc:450

#18 0x61cbbc08 in base::MessageLoop::DeferOrRunPendingTask(this=this@entry=0x62b81250, pending_task=...) at../../base/message_loop/message_loop.cc:462

#19 0x61cbc312 in base::MessageLoop::DoWork (this=0x62b81250) at../../base/message_loop/message_loop.cc:576

#20 0x61c9fd8c in base::MessagePumpLibevent::Run (this=0x5c4e41f0,delegate=0x62b81250) at../../base/message_loop/message_pump_libevent.cc:232

#21 0x61cbbf3e in base::MessageLoop::RunHandler (this=0x62b81250)at ../../base/message_loop/message_loop.cc:400

#22 0x61cc3540 in base::RunLoop::Run (this=this@entry=0x63bffbf8)at ../../base/run_loop.cc:49

#23 0x61cbb570 in base::MessageLoop::Run(this=this@entry=0x62b81250) at../../base/message_loop/message_loop.cc:293

#24 0x61ccbe02 in base::Thread::Run (this=this@entry=0x62b64488,message_loop=message_loop@entry=0x62b81250) at../../base/threading/thread.cc:172

#25 0x61855afe in content::BrowserThreadImpl::IOThreadRun //io线程(this=this@entry=0x62b64488,message_loop=message_loop@entry=0x62b81250) at../../content/browser/browser_thread_impl.cc:217

#26 0x61855bca in content::BrowserThreadImpl::Run(this=0x62b64488, message_loop=0x62b81250) at../../content/browser/browser_thread_impl.cc:252

#27 0x61ccc1a6 in base::Thread::ThreadMain (this=0x62b64488) at../../base/threading/thread.cc:225

#28 0x61cc9fde in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

#29 0x4017ba5c in __thread_entry () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#30 0x4017bbd8 in pthread_create () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so





virtual scoped_ptr<SSLClientSocket> CreateSSLClientSocket(

scoped_ptr<ClientSocketHandle> transport_socket,

const HostPortPair& host_and_port,

const SSLConfig& ssl_config,

const SSLClientSocketContext& context) OVERRIDE {



#if defined(USE_OPENSSL)/默认的使用openssl

return scoped_ptr<SSLClientSocket>(

new SSLClientSocketOpenSSL(transport_socket.Pass(),host_and_port,

ssl_config, context));

#elif defined(USE_NSS) ||defined(OS_MACOSX) || defined(OS_WIN)

return scoped_ptr<SSLClientSocket>(

new SSLClientSocketNSS(nss_task_runner.get(),

transport_socket.Pass(),

host_and_port,

ssl_config,

context));

#else

NOTIMPLEMENTED();

return scoped_ptr<SSLClientSocket>();

#endif

}



SSLClientSocketOpenSSL::Connect (ssl_clent_socket_openssl.cc)

-> init() ,这里面会根据sslconfig信息把使用的ssl版本信息设置到SslSetClearMask也就是options.里面。会根据版本等设置生成option,调用SSL_set_options(ssl_,options.set_mask); 以及 SSL_clear_options(ssl_,options.clear_mask); 设置到openssl模块里面,也就是SSL结构的options成员里。

GotoState(STATE_HANDSHAKE); 设置状态

rv = DoHandshakeLoop(OK);//下面是握手的逻辑

----> int SSLClientSocketOpenSSL::DoHandshakeLoop(intlast_io_result) { //这个循环会完成证书握手,证书验证。

int rv = last_io_result;

do {

State state = next_handshake_state_;

GotoState(STATE_NONE);

switch (state) {

case STATE_HANDSHAKE:

rv = DoHandshake();

break;

case STATE_VERIFY_CERT:

DCHECK(rv == OK);

rv = DoVerifyCert(rv);

break;

case STATE_VERIFY_CERT_COMPLETE:

rv = DoVerifyCertComplete(rv);

break;

case STATE_NONE:

default:

rv = ERR_UNEXPECTED;

NOTREACHED() << "unexpected state" <<state;

break;

}



bool network_moved = DoTransportIO();

if (network_moved && next_handshake_state_ ==STATE_HANDSHAKE) {

rv = OK; // This causes us to stay in the loop.

}

} while (rv != ERR_IO_PENDING && next_handshake_state_!= STATE_NONE);

return rv;





看一下SSLClientSocketOpenSSL::DoHandShake

->SSL_do_handshake(SSL* ssl) // opensslssl_lib.c因为之前SSLClientSocketOpenSSL::init时,已经把配置设置到了SSL结构的option里,所以这里调用openssl的接口就开始握手了。握手结束后,就获取servier的证书并验证。当然,如果client证书也需要的话还得提供client证书。







Callstack:

#0 SSL_do_handshake(s=0x66102b28) at../../third_party/openssl/openssl/ssl/ssl_lib.c:2620

#1 0x620fc56a in net::SSLClientSocketOpenSSL::DoHandshake(this=this@entry=0x659c0de0) at../../net/socket/ssl_client_socket_openssl.cc:804

#2 0x620fc86a in net::SSLClientSocketOpenSSL::DoHandshakeLoop(this=this@entry=0x659c0de0, last_io_result=last_io_result@entry=0)at ../../net/socket/ssl_client_socket_openssl.cc:1002

#3 0x620fc8ea innet::SSLClientSocketOpenSSL::Connect(base::Callback<void(int)> const&) (this=0x659c0de0, callback=...) at../../net/socket/ssl_client_socket_openssl.cc:428

#4 0x620fd368 in net::SSLConnectJob::DoSSLConnect(this=this@entry=0x658f9b08) at../../net/socket/ssl_client_socket_pool.cc:324

#5 0x620fe886 in net::SSLConnectJob::DoLoop(this=this@entry=0x658f9b08, result=<optimized out>) at../../net/socket/ssl_client_socket_pool.cc:205

#6 0x620fe8ae in net::SSLConnectJob::OnIOComplete(this=0x658f9b08, result=<optimized out>) at../../net/socket/ssl_client_socket_pool.cc:169

#7 0x620fd172 in Run (a1=@0x63b4194c: 0, object=<optimizedout>, this=0x63b41930) at ../../base/bind_internal.h:190

#8 MakeItSo (a2=@0x63b4194c: 0, a1=<optimized out>,runnable=...) at ../../base/bind_internal.h:898

#9 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(net::SSLConnectJob::*)(int)>, void (net::SSLConnectJob*, int),void (base::internal::UnretainedWrapper<net::SSLConnect

Job>)>, void (net::SSLConnectJob*,int)>::Run(base::internal::BindStateBase*, int const&)(base=<optimized out>, x2=@0x63b4194c: 0) at../../base/bind_internal.h:1224

#10 0x620fa520 in Run (a1=@0x63b4194c: 0, this=0x63b41950) at../../base/callback.h:441

#11 net::ClientSocketHandle::OnIOComplete (this=<optimizedout>, result=0) at ../../net/socket/client_socket_handle.cc:143

#12 0x620f9d46 in Run (a1=@0x63b41984: 0, object=<optimizedout>, this=0x63b41968) at ../../base/bind_internal.h:190

#13 MakeItSo (a2=@0x63b41984: 0, a1=<optimized out>,runnable=...) at ../../base/bind_internal.h:898

#14 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(net::ClientSocketHandle::*)(int)>, void(net::ClientSocketHandle*, int), void(base::internal::UnretainedWrapper<net::

ClientSocketHandle>)>, void (net::ClientSocketHandle*,int)>::Run(base::internal::BindStateBase*, int const&)(base=<optimized out>, x2=@0x63b41984: 0) at../../base/bind_internal.h:1224

#15 0x6217ee34 in Run (a1=@0x63b41984: 0, this=0x63b4198c) at../../base/callback.h:441

#16 net::internal::ClientSocketPoolBaseHelper::InvokeUserCallback(this=0x64146c18, handle=<optimized out>) at../../net/socket/client_socket_pool_base.cc:1133

#17 0x621800c8 in Run (a1=@0x65943ae8: 0x658f9d00,object=<optimized out>, this=0x63b41a50) at../../base/bind_internal.h:190

#18 MakeItSo (a2=@0x65943ae8: 0x658f9d00, weak_ptr=...,runnable=...) at ../../base/bind_internal.h:909

#19 base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void(net::internal::ClientSocketPoolBaseHelper::*)(net::ClientSocketHandle*)>,void (net::internal::ClientSocketPoolBaseHel

per*, net::ClientSocketHandle*), void(base::WeakPtr<net::internal::ClientSocketPoolBaseHelper>,net::ClientSocketHandle*)>, void(net::internal::ClientSocketPoolBaseHelper*,net::ClientSocketHandle*)>::Run(base::

internal::BindStateBase*) (base=0x65943ad0) at../../base/bind_internal.h:1253

#20 0x61efdb5c in Run (this=0x63b41b60) at../../base/callback.h:401

#21 base::MessageLoop::RunTask (this=this@entry=0x60a163a8,pending_task=...) at ../../base/message_loop/message_loop.cc:450

#22 0x61efdc08 in base::MessageLoop::DeferOrRunPendingTask(this=this@entry=0x60a163a8, pending_task=...) at../../base/message_loop/message_loop.cc:462

#23 0x61efe312 in base::MessageLoop::DoWork (this=0x60a163a8) at../../base/message_loop/message_loop.cc:576

#24 0x61ee1d8c in base::MessagePumpLibevent::Run (this=0x60a164a0,delegate=0x60a163a8) at../../base/message_loop/message_pump_libevent.cc:232

#25 0x61efdf3e in base::MessageLoop::RunHandler (this=0x60a163a8)at ../../base/message_loop/message_loop.cc:400

#26 0x61f05540 in base::RunLoop::Run (this=this@entry=0x63b41bf8)at ../../base/run_loop.cc:49

#27 0x61efd570 in base::MessageLoop::Run(this=this@entry=0x60a163a8) at../../base/message_loop/message_loop.cc:293

#28 0x61f0de02 in base::Thread::Run (this=this@entry=0x60a14800,message_loop=message_loop@entry=0x60a163a8) at../../base/threading/thread.cc:172

#29 0x61a97afe in content::BrowserThreadImpl::IOThreadRun//io线程(this=this@entry=0x60a14800,message_loop=message_loop@entry=0x60a163a8) at../../content/browser/browser_thread_impl.cc:217

#30 0x61a97bca in content::BrowserThreadImpl::Run(this=0x60a14800, message_loop=0x60a163a8) at../../content/browser/browser_thread_impl.cc:252

#31 0x61f0e1a6 in base::Thread::ThreadMain (this=0x60a14800) at../../base/threading/thread.cc:225



可以从下面代码知道要控制ssl版本的使用,应该从那里入手:

int SSLClientSocketOpenSSL::Init() {

DCHECK(!ssl_);

DCHECK(!transport_bio_);



SSLContext* context = SSLContext::GetInstance();

crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);



ssl_ = SSL_new(context->ssl_ctx());

if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this))

return ERR_UNEXPECTED;



if (!SSL_set_tlsext_host_name(ssl_,host_and_port_.host().c_str()))

return ERR_UNEXPECTED;



trying_cached_session_ =context->session_cache()->SetSSLSessionWithKey(

ssl_, GetSocketSessionCacheKey(*this));



BIO* ssl_bio = NULL;

// 0 => use default buffer sizes.

if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))

return ERR_UNEXPECTED;

DCHECK(ssl_bio);

DCHECK(transport_bio_);



SSL_set_bio(ssl_, ssl_bio, ssl_bio);



// OpenSSL defaults some options to on, others to off. To avoidambiguity,

// set everything we care about to an absolute value.

SslSetClearMask options;

options.ConfigureFlag(SSL_OP_NO_SSLv2, true);

bool ssl3_enabled =(ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); //要想禁用ssl3就得把ssl_config.version_min改了。

options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled);

bool tls1_enabled = (ssl_config_.version_min <=SSL_PROTOCOL_VERSION_TLS1 &&

ssl_config_.version_max >=SSL_PROTOCOL_VERSION_TLS1);

options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled);

bool tls1_1_enabled =

(ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1&&

ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1);

options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled);

bool tls1_2_enabled =

(ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2&&

ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2);

options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled);



options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);



// TODO(joth): Set this conditionally, seehttp://crbug.com/55410

options.ConfigureFlag(SSL_OP_LEGACY_SERVER_CONNECT, true);



SSL_set_options(ssl_,options.set_mask);

SSL_clear_options(ssl_, options.clear_mask);



如果改了ssl_config.version_min改了,可以在这里加一个打印,看有没有效果。

查找ssl_config.version_min使用点。赋值的地方。





SSLConfig结构(ssl_client_socket_openssl.h中):

// The minimum and maximumprotocol versions that are enabled.

// SSL 3.0 is 0x0300, TLS 1.0is 0x0301, TLS 1.1 is 0x0302, and so on.

// (Use theSSL_PROTOCOL_VERSION_xxx enumerators defined above.)

// SSL 2.0 is not supported.If version_max < version_min, it means no

// protocol versions areenabled.

uint16 version_min;

uint16 version_max;



SSLConfig构造函数有version_min默认值,要修改一下。

SSLConfigService, SSLConfigServiceManager,SSLConfigServiceManagerPref的关联是啥?干什么的?

SSLConfigService是基类,可以检查比较新旧两个配置,如果发生变化,那么就可以通知注册进来的一些observer配置变化了。

// This SSLConfigService always returns the default SSLConfigsettings. It is

// mainly useful for unittests, or for platforms that do not havea native

// implementation of SSLConfigService yet.

//基本没什么特殊功能,维护了一份配置

class NET_EXPORT SSLConfigServiceDefaults: public SSLConfigService {





// An SSLConfigService which stores a cached version of thecurrent SSLConfig

// prefs, which are updated by SSLConfigServiceManagerPref whenthe prefs

// change.

//提供了对可以persistentsslprefs的支持,当ui线程发现sslprefs发生变化时,会通过SSLConfigServiceManagerPref来从pref读取配置,生成新的ssl配置结构,并设置给SSLConfigServicePref,它比较新的和旧的,如果有改变,就notifyobservers.注意notify的操作在io线程完成。

class SSLConfigServicePref: public net::SSLConfigService {

用的哪个SSLConfigService?



SSLConfigServiceManager是一个抽象类,作为接口。用来创建SSLConfigService实例。



class SSLConfigServiceManagerPref : publicSSLConfigServiceManager {

它有一些成员,比如ssl_version_min_,成员类型都是PrefMember,这些成员描述了configService关心的参数。在够造函数里,这些成员都被注册了一个callback:SSLConfigServiceManagerPref::OnPreferenceChanged.当这些成员变了,就调用该callback.callback会从新读取这些成员的值,并付给一个SSLConfig结构。然后调用SSLConfigServicePref::SetNewSSLConfig,

void SSLConfigServicePref::SetNewSSLConfig(

const net::SSLConfig& new_config) {

net::SSLConfig orig_config = cached_config_;

cached_config_ = new_config;//替换当前的config.

ProcessConfigUpdate(orig_config, new_config);

}

->void SSLConfigService::ProcessConfigUpdate(const SSLConfig&orig_config,

const SSLConfig&new_config) {

->NotifySSLConfigChange, 通知监听者。

那么这些pref究竟谁改得?用户改的么?监听者都有谁?SSLClientSocketPool是一个监听者,其构造函数中把自己注册了进来。当SSLClientSocketPool收到改动通知后,会做一些操作。当然改动后的内容还是得从configsrevice来获取。

谁会修改配置以后再看。

先试一下在SSLConfig构造函数中修改最低版本看能否起作用。

ssl_config.cc中有constuint16 kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_SSL3;

把他的值改成SSL_PROTOCOL_VERSION_TLS1



下面再分析一下ssl握手的流程:

SSLClientSocketOpenSSL::DoHandshakeLoop

int rv = last_io_result;

do {

// Default to STATE_NONEfor next state.

// (This is a quirkcarried over from the windows

// implementation. Itmakes reading the logs a bit harder.)

// State handlers canand often do call GotoState just

// to stay in thecurrent state.

State state =next_handshake_state_;

GotoState(STATE_NONE);

switch (state) {

case STATE_HANDSHAKE:

rv = DoHandshake();

break;

caseSTATE_VERIFY_CERT:

DCHECK(rv == OK);

rv =DoVerifyCert(rv);

break;

caseSTATE_VERIFY_CERT_COMPLETE:

rv =DoVerifyCertComplete(rv);

break;

case STATE_NONE:

default:

rv = ERR_UNEXPECTED;

NOTREACHED() <<"unexpected state" << state;

break;

}



bool network_moved =DoTransportIO();

if (network_moved &&next_handshake_state_ == STATE_HANDSHAKE) {

// In general we exitthe loop if rv is ERR_IO_PENDING. In this

// special case wekeep looping even if rv is ERR_IO_PENDING because

// the transport IOmay allow DoHandshake to make progress.

rv = OK; // Thiscauses us to stay in the loop.

}

} while (rv !=ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);

return rv;



首先进入 rv = DoHandshake();调用opensslapi执行handshake,如果异步没完成,那么,状态依然保持STATE_HANDSHAKE.结果是IOPending。在Dohandleshakeloop里就执行一次TransportIO,也就是本socket

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值