Cronet代码解析-URLRequest

简介

Cronet是chromium的网络协议栈,具有如下特点。

  • 提供了从传输层到应用层的完整网络库功能。
  • 极佳的跨平台性,覆盖所有主流操作系统:iOS, Android, linux, macOS, win。
  • 除了应用层由于支持跨平台,使用了不同语言封装(java | objective-C),底层共用一套C++代码,性能很高。
  • 提供多种协议支持:http/spdy/quic等。

最重要的是,这个项目Google开源出来了。
其中,http协议常用的请求方式为使用URLRequest,本章用于记录对URLRequest代码的学习分析。

请求流程

基本流程
应用层调用URLRequest接口 -> Create new URLRequestJob -> Create URLRequestHttpJob子类(根据协议类型) -> HttpTransaction创建会话 -> socket层创建连接…

代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 对外接口
URLRequest(const GURL& url,
RequestPriority priority,
Delegate* delegate,
const URLRequestContext* context,
NetworkDelegate* network_delegate);
// 开始发送一个请求
void URLRequest::Start() {
/../
StartJob(URLRequestJobManager::GetInstance()->CreateJob(
this, network_delegate_));//调用URLRequestJobManager的创建job的方法
}
// 初始化子类并执行
void URLRequest::StartJob(URLRequestJob* job) {
/.../
job_->Start();//调用job的Start()方法
}
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 子类接口
URLRequestJob(URLRequest* request, NetworkDelegate* network_delegate);
// 子类类型及其对应的工厂类
static const SchemeToFactory kBuiltinFactories[] = { //定义内置请求类型及其对应的job类型
{ "http", URLRequestHttpJob::Factory },
{ "https", URLRequestHttpJob::Factory },
#if !defined(OS_IOS)
{ "ws", URLRequestHttpJob::Factory },
{ "wss", URLRequestHttpJob::Factory },
#endif // !defined(OS_IOS)
};
// 初始化一个新job
URLRequestJob* URLRequestJobManager::CreateJob(
URLRequest* request, NetworkDelegate* network_delegate) const {
DCHECK(IsAllowedThread());
// If we are given an invalid URL, then don't even try to inspect the scheme.
if (!request->url().is_valid())
return new URLRequestErrorJob(request, network_delegate, ERR_INVALID_URL);
// We do this here to avoid asking interceptors about unsupported schemes.
const URLRequestJobFactory* job_factory =
request->context()->job_factory(); //获取上下文中的工厂类实例,用于产出job实例
const std::string& scheme = request->url().scheme(); // already lowercase//获取schema,即请求类型:http/ftp等
if (!job_factory->IsHandledProtocol(scheme)) {//是否为合法的请求类型
return new URLRequestErrorJob(
request, network_delegate, ERR_UNKNOWN_URL_SCHEME);
}
URLRequestJob* job = job_factory->MaybeCreateJobWithProtocolHandler(//创建job,请求类型来自外部
scheme, request, network_delegate);
if (job)
return job;
// See if the request should be handled by a built-in protocol factory.
for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) {//上面没有创建成功,尝试内部类型创建
if (scheme == kBuiltinFactories[i].scheme) {
URLRequestJob* new_job =
(kBuiltinFactories[i].factory)(request, network_delegate, scheme);
DCHECK(new_job); // The built-in factories are not expected to fail!
return new_job;
}
}
/.../
}
// 工厂方法创建job
URLRequestJob* URLRequestJobFactoryImpl::MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
URLRequest* request,
NetworkDelegate* network_delegate) const {
ProtocolHandlerMap::const_iterator it = protocol_handler_map_.find(scheme);
if (it == protocol_handler_map_.end())
return NULL;
return it->second->MaybeCreateJob(request, network_delegate);
}
/* DataProtocolHandler */
// TODO(shalev): Move this to URLRequestJobFactoryImpl.
class NET_EXPORT ProtocolHandler
URLRequestJob* DataProtocolHandler::MaybeCreateJob( //真正创建是由DataProtocolHandler来执行
URLRequest* request, NetworkDelegate* network_delegate) const {
return new URLRequestDataJob(request, network_delegate);
}
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
以HttpJob为例,介绍一个job具体怎样工作
void URLRequestHttpJob::Start() {
  /../ 
 
  request_info_.extra_headers.SetHeaderIfMissing(
      HttpRequestHeaders::kUserAgent,
      http_user_agent_settings_ ?
          http_user_agent_settings_->GetUserAgent() : std::string());
  AddExtraHeaders(); //添加额外的http header信息
  AddCookieHeaderAndStart(); //从cookie中获取信息并启动
}
 
 
 
void URLRequestHttpJob::AddExtraHeaders() {
  SdchManager* sdch_manager = request()->context()->sdch_manager();//获取sdch压缩方法控制结构
  if (!request_info_.extra_headers.HasHeader(
      HttpRequestHeaders::kAcceptEncoding)) {
    bool advertise_sdch = sdch_manager != NULL && request()->method() != "POST"; //sdch不允许使用post方式
    if (advertise_sdch) {
      SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url());
      if (rv != SDCH_OK) {
        advertise_sdch = false;
        SdchManager::SdchErrorRecovery(rv);
        request()->net_log().AddEvent(
            NetLog::TYPE_SDCH_DECODING_ERROR,
            base::Bind(&NetLogSdchResourceProblemCallback, rv));
      }
    }
    std::string advertised_encodings = "gzip, deflate";
    if (advertise_sdch)
      advertised_encodings += ", sdch";
    if (advertise_brotli)
      advertised_encodings += ", br";
    /../
    }
  }
}
 
 
/*****************************************************************************/
sdch压缩操作
void SdchManager::DictionarySet::AddDictionary(
    const std::string& server_hash,
    const scoped_refptr<base::RefCountedData<SdchDictionary>>& dictionary) {
  DCHECK(dictionaries_.end() == dictionaries_.find(server_hash));
  dictionaries_[server_hash] = dictionary;
}
const std::string* SdchManager::DictionarySet::GetDictionaryText(
    const std::string& server_hash) const {
  auto it = dictionaries_.find(server_hash);
  if (it == dictionaries_.end())
    return nullptr;
  return &it->second->data.text();
}
/*****************************************************************************/
void URLRequestHttpJob::AddCookieHeaderAndStart() {
  // If the request was destroyed, then there is no more work to do.
  if (!request_)
    return;
  CookieStore* cookie_store = request_->context()->cookie_store();
  if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) { //如果有coockie,先获取cookie中的信息并执行连接
    CookieOptions options;
    options.set_include_httponly();
    url::Origin requested_origin(request_->url());
    if (!network_delegate() ||
        !network_delegate()->AreExperimentalCookieFeaturesEnabled()) {
      options.set_include_same_site();
    } else if (requested_origin.IsSameOriginWith(
                   url::Origin(request_->first_party_for_cookies())) &&
               (IsMethodSafe(request_->method()) ||
                requested_origin.IsSameOriginWith(request_->initiator()))) {
      options.set_include_same_site();
    }
    cookie_store->GetCookieListWithOptionsAsync(
        request_->url(), options,
        base::Bind(&URLRequestHttpJob::SetCookieHeaderAndStart, //设置cookie并执行连接
                   weak_factory_.GetWeakPtr()));
  } else {
    DoStartTransaction();//否则直接执行连接
  }
}
 
 
 
 
void URLRequestHttpJob::DoStartTransaction() {
  // We may have been canceled while retrieving cookies.
  if (GetStatus().is_success()) {
    StartTransaction();
  } else {
    NotifyCanceled();
  }
}
 
void URLRequestHttpJob::StartTransaction() {
  if (network_delegate()) {  //有代理先走代理进行连接
    OnCallToDelegate();
    int rv = network_delegate()->NotifyBeforeSendHeaders(
        request_, notify_before_headers_sent_callback_,
        &request_info_.extra_headers);
    // If an extension blocks the request, we rely on the callback to
    // MaybeStartTransactionInternal().
    if (rv == ERR_IO_PENDING)
      return;
    MaybeStartTransactionInternal(rv);
    return;
  }
  StartTransactionInternal();//否则发起正常连接
}
 
 
 
 
void URLRequestHttpJob::StartTransactionInternal() {
  bool invalid_header_values_in_rfc7230 = false;
  for (HttpRequestHeaders::Iterator it(request_info_.extra_headers);
       it.GetNext();) {
    if (!HttpUtil::IsValidHeaderValueRFC7230(it.value())) {
      invalid_header_values_in_rfc7230 = true;
      break;
    }
  }
  UMA_HISTOGRAM_BOOLEAN("Net.HttpRequest.ContainsInvalidHeaderValuesInRFC7230",
                        invalid_header_values_in_rfc7230);
  int rv;
  if (network_delegate()) {
    network_delegate()->NotifySendHeaders(
        request_, request_info_.extra_headers);
  }
  if (transaction_.get()) { //已经存在现成的连接
    rv = transaction_->RestartWithAuth(auth_credentials_, start_callback_); //重新验证
    auth_credentials_ = AuthCredentials();
  } else {
    DCHECK(request_->context()->http_transaction_factory());
    rv = request_->context()->http_transaction_factory()->CreateTransaction( //否则通过连接工厂类产生新的连接
        priority_, &transaction_, request_->GetRequestID());
    /../
    }
    if (rv == OK) {
      /.../
          !throttling_entry_->ShouldRejectRequest(*request_)) {
        rv = transaction_->Start( //执行连接启动
            &request_info_, start_callback_, request_->net_log());
        start_time_ = base::TimeTicks::Now();
      } else {
        // Special error code for the exponential back-off module.
        rv = ERR_TEMPORARILY_THROTTLED;
      }
    }
  }
  if (rv == ERR_IO_PENDING)
    return;
}
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// 创建会话
int HttpCache::CreateTransaction(RequestPriority priority, //由httpCache继承http_cache_transaction进行具体执行
scoped_ptr<HttpTransaction>* trans,
const BdNetLogID& request_id) {
// Do lazy initialization of disk cache if needed.
if (!disk_cache_.get()) {
// We don't care about the result.
CreateBackend(NULL, CompletionCallback());
}
HttpCache::Transaction* transaction =
new HttpCache::Transaction(priority, this, request_id);
if (bypass_lock_for_test_)
transaction->BypassLockForTest();
if (fail_conditionalization_for_test_)
transaction->FailConditionalizationForTest();
trans->reset(transaction);
return OK;
}
int HttpCache::Transaction::Start(const HttpRequestInfo* request,
                                  const CompletionCallback& callback,
                                  const BoundNetLog& net_log) {
  if (!cache_.get())
    return ERR_UNEXPECTED;
  SetRequest(net_log, request);
  // We have to wait until the backend is initialized so we start the SM.
  next_state_ = STATE_GET_BACKEND; //设置初始状态,首先连接后端
  int rv = DoLoop(OK);//执行loop进行连接以及IO操作
  // Setting this here allows us to check for the existence of a callback_ to
  // determine if we are still inside Start.
  if (rv == ERR_IO_PENDING)
    callback_ = callback;
  return rv;
}
 
 
//Doloop方法,状态驱动,使其完成连接建立、IO流程一系列流程
//-----------------------------------------------------------------------------
// A few common patterns: (Foo* means Foo -> FooComplete)
//
// 1. Not-cached entry:
//   Start():
//   GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* ->
//   SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
//   CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* ->
//   PartialHeadersReceived
//
//   Read():
//   NetworkRead* -> CacheWriteData*
//
// 2. Cached entry, no validation:
//   Start():
//   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
//   -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
//   BeginCacheValidation() -> SetupEntryForRead()
//
//   Read():
//   CacheReadData*
//
// 3. Cached entry, validation (304):
//   Start():
//   GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
//   -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
//   BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest ->
//   UpdateCachedResponse -> CacheWriteUpdatedResponse* ->
//   UpdateCachedResponseComplete -> OverwriteCachedResponse ->
//   PartialHeadersReceived
//
//   Read():
//   CacheReadData*
//
/.../
/----------------------------------------------------------------------------------/
/*状态驱动 执行这整个后端连接,发送 接受 写入的流程 */
int HttpCache::Transaction::DoLoop(int result) {
  DCHECK(next_state_ != STATE_NONE);
  int rv = result;
  do {
    State state = next_state_;
    next_state_ = STATE_NONE;
    switch (state) {
      case STATE_GET_BACKEND:
        DCHECK_EQ(OK, rv);
        rv = DoGetBackend();
        break;
      case STATE_GET_BACKEND_COMPLETE:
        rv = DoGetBackendComplete(rv);
        break;
      case STATE_INIT_ENTRY:
        DCHECK_EQ(OK, rv);
        rv = DoInitEntry();
        break;
      case STATE_OPEN_ENTRY:
        DCHECK_EQ(OK, rv);
        rv = DoOpenEntry();
        break;
      /.../
      case STATE_CACHE_READ_RESPONSE:
        DCHECK_EQ(OK, rv);
        rv = DoCacheReadResponse();
        break;
      case STATE_CACHE_READ_RESPONSE_COMPLETE:
        rv = DoCacheReadResponseComplete(rv);
        break;
      
      case STATE_CACHE_QUERY_DATA:
        DCHECK_EQ(OK, rv);
        rv = DoCacheQueryData();
        break;
      case STATE_SEND_REQUEST:
        DCHECK_EQ(OK, rv);
        rv = DoSendRequest();
        break;
      case STATE_SEND_REQUEST_COMPLETE:
        rv = DoSendRequestComplete(rv);
        break;
      case STATE_CACHE_WRITE_RESPONSE:
        DCHECK_EQ(OK, rv);
        rv = DoCacheWriteResponse();
        break;
     
      case STATE_CACHE_WRITE_DATA:
        rv = DoCacheWriteData(rv);
        break;
      default:
        NOTREACHED() << "bad state";
        rv = ERR_FAILED;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
  if (rv != ERR_IO_PENDING && !callback_.is_null()) {
    read_buf_ = NULL// Release the buffer before invoking the callback.
    base::ResetAndReturn(&callback_).Run(rv);
  }
  return rv;
}
 
 
// Creates the disk cache entry associated with |key|, returning an
  // ActiveEntry in |*entry|. |trans| will be notified via its IO callback if
  // this method returns ERR_IO_PENDING.
  int CreateEntry(const std::string& key, ActiveEntry** entry,
                  Transaction* trans);
 
 
int HttpCache::Transaction::DoGetBackend() {
  cache_pending_ = true;
  next_state_ = STATE_GET_BACKEND_COMPLETE;
  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND);
  return cache_->GetBackendForTransaction(this);
}
 
int HttpCache::Transaction::DoOpenEntry() {
  DCHECK(!new_entry_);
  next_state_ = STATE_OPEN_ENTRY_COMPLETE;
  cache_pending_ = true;
  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
  first_cache_access_since_ = TimeTicks::Now();
  return cache_->OpenEntry(cache_key_, &new_entry_, this);
}
 
int HttpCache::Transaction::DoCreateEntry() {
  DCHECK(!new_entry_);
  next_state_ = STATE_CREATE_ENTRY_COMPLETE;
  cache_pending_ = true;
  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY);
  return cache_->CreateEntry(cache_key_, &new_entry_, this);
}
 
 
int HttpCache::Transaction::DoCacheReadResponse() {
  DCHECK(entry_);
  next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE;
  io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex);
  read_buf_ = new IOBuffer(io_buf_len_);
  net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
  return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(),
                                      io_buf_len_, io_callback_);
}