内容目录
1.2.2 browser代码中ssl版本的选择以及握手的过程 7
1.4.1.1 basic authentication 20
1.4.1.2 Digest access authentication 21
1.6 http_cache_transaction的doloop详细步骤: 30
1.7 http_cache_transaction的doloop中backend的建立 34
1.8 http_cache_transaction的init/openentry 38
1.10 Add transaction to entry 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
3.1.2 Client端Ip地址,port如果变化如何通知servier 95
4.2.3.2 Stream data exchange 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.
spdy将要被google抛弃。
http2.0
QUIC,UDP
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上演化来,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