chromium网络栈学习

内容目录

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 blink中httpcache模块分析 24

1.6 http_cache_transaction的doloop详细步骤: 30

1.7 http_cache_transaction的doloop中backend的建立 34

1.8 http_cache_transaction的init/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,在HttpNetworkTransaction的DoLoop里执行该任务。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 Client端Ip地址,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 脚本

SOCKS,TUNNEL



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.youkuaiyun.com/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上演化来,SSL是netscape的,TLS是IETF的,TLS和SSL使用起来差不多。但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.cc的build函数中,ssl_config_service就是SSLConfigServiceDefaults。它使用默认的ssl设置。



httpNetworkTransaction构造函数中:

session→ssl_config_service()→GetSSLConfig(&server_ssl_config_);//数据来自session的ssl_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::kDefaultSSLVersionMin和net::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应该不一样。实际上经调试,用的factory是DefaultClientSocketFactory。(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) // openssl的ssl_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.

//提供了对可以persistent的ssl的prefs的支持,当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();调用openssl的api执行handshake,如果异步没完成,那么,状态依然保持STATE_HANDSHAKE.结果是IOPending。在Dohandleshakeloop里就执行一次TransportIO,也就是本socket数据读写,如果有数据io发生,那么就不退出dohandleshakeloop,返回值改为ok,因为此时状态还是<

14-Cronet技术全景:Chromium网络栈完整解析-Android系统底层用到的开源库 Cronet是Chromium网络栈的Android封装库,提供与Chrome浏览器相同的高性能网络能力。核心特性包括多协议支持(HTTP/1.1/2/3)、性能优化(连接池、智能缓存)和安全增强(HSTS、证书验证)。架构分为四层:Java API层提供简洁接口;JNI桥接层(2,453行)处理Java与C++交互;C++核心网络层(436,000+行)实现协议处理;平台集成层处理Android特定功能。代码规模达486,000行,支持QUIC 0-RTT等高级特性,广泛应用于Google系及主流社交应用 阅读详情

相关推荐

学习记录(十一)--Pattern Recognition投稿记录

上一周特别忽然通知统计建模要答辩,确定是否晋级国赛,一直在准备答辩的事情,所以上一周没有总结周汇报,深刻检讨!!!不过结果是好的,我们组第二名晋级哦。这周主要是跟大家分享一下我投稿PR(Pattern Recognition)的一个时间线,以及投稿后的工作。一、PR从投稿到接收的时间线2025.4.3 Major Revision(ddl4.23) 当时正在弄比赛和另一个着急推进的文章2025.5.30 Minor Revision 这次小修基本上只有一些格式和简单一点点问题。

qq_54949944的博客 1923

SigFit实战:从FEA到光学仿真的热力耦合分析全流程解析

在光机系统与芯片封装等精密工程领域,热与力的耦合效应是影响产品性能与可靠性的核心物理问题。有限元分析(FEA)是预测结构在热、力载荷下变形与应力的基础工具,但其结果通常无法直接用于评估光学性能。这需要一座桥梁,将物理场数据转化为光学设计语言。其核心原理在于数据映射与面形表征技术,例如通过泽尼克多项式拟合,将离散的节点位移分解为离焦、像散等标准光学像差。这项技术的工程价值在于,它实现了多物理场仿真的闭环,使工程师能在设计阶段精准预测热变形或应力对波前误差、调制传递函数等关键光学指标的影响。其典型应用场景包括高

weixin_28630185的博客 343

不只是安装:用OrbbecSDK_ROS2玩转深度相机点云、滤波与DDS调优

本文深入探讨了如何通过OrbbecSDK_ROS2实现深度相机的高级应用,包括点云处理、深度图优化和DDS调优。详细介绍了点云采集与可视化技巧、多种滤波算法的配置与组合策略,以及针对高带宽数据传输的DDS高级调优方法,帮助开发者在机器人导航和三维重建等场景中提升性能。

weixin_29246195的博客 787

《YOLOv8实例分割实战:训练自己的数据集 》(视频课程)

本课程将手把手地教大家使用labelme标注和使用YOLOv8训练自己的数据集,完成一个多目标实例分割实战项目。

bai666ai的博客 790

爬取信用中国里面的行政处罚

result字段名为行政处罚文书号、处罚决定日期、处罚内容、处罚金额、违法事实、处罚机关、公司名称,行政处罚次数。file_path=r'E:\Data analyze\python\行政处罚爬虫/'#路径需要按实际修改。writer = pd.ExcelWriter('统计.xlsx')# 写入Excel文件。src_workbook=file_path+r'行政处罚(名单).xls' #表格名称也要更改。# keyword = input("输入爬取的公司全称必须是全称")

qq_42863025的博客 1675

《网络安全自学教程》- 防火墙原理分析与Windows防火墙使用配置

防火墙分类及原理,Windows开启防火墙,Windows防火墙添加策略,

wangyuxiang946的博客 1万+

在claude code desktop中安装pdf处理skill的实战教程

本文介绍了在Claude Code Desktop中安装PDF处理Skill的详细教程。针对国内用户使用第三方API时无法直接调用官方插件的问题,提供了完整的解决方案。教程从下载Anthropic官方Skills源码开始,逐步演示了如何将PDF处理模块打包、上传至Claude Code Desktop,并最终成功加载使用。整个过程采用全流程拆解方式,确保新手也能快速上手。通过本文,读者可以掌握在非官方环境下扩展Claude Code功能的方法,从而提升工作效率

weixin_43178406的博客 9万+

复旦微实现串口在线升级BOOT.BIN

将该 demo 生成的 app(升级用)和 fsbl、最简化 bit 文件(可选)打包成 BOOT.BIN,作为 golden image 烧写在 qspi flash 偏移 0 地址开始的位置,其中最简化 bit 文件为在线升级功能提供必要的物理通道(如果不需要,可以不打包该文件),golden image 一旦发布基本不需要进行升级,由该 golden image 负责和上位机进行通信交互,完成业务 app、业务 bit 文件、uboot 以及操作系统 image 等文件在线升级,在qspi flash

wangjie36的博客 3174

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

上一篇: blink渲染知识16 - raster干了什么
下一篇: chromium+blink网页加载流程
csshell2002
博客等级 码龄11年 30粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值