1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/flip/flip_network_transaction.h" 6 7 #include "base/compiler_specific.h" 8 #include "base/logging.h" 9 #include "base/scoped_ptr.h" 10 #include "base/stats_counters.h" 11 #include "net/base/host_resolver.h" 12 #include "net/base/io_buffer.h" 13 #include "net/base/load_flags.h" 14 #include "net/base/net_errors.h" 15 #include "net/base/net_util.h" 16 #include "net/base/upload_data_stream.h" 17 #include "net/flip/flip_stream.h" 18 #include "net/http/http_network_session.h" 19 #include "net/http/http_request_info.h" 20 #include "net/http/http_response_info.h" 21 22 using base::Time; 23 24 namespace net { 25 26 //----------------------------------------------------------------------------- 27 28 FlipNetworkTransaction::FlipNetworkTransaction(HttpNetworkSession* session) 29 : ALLOW_THIS_IN_INITIALIZER_LIST( 30 io_callback_(this, &FlipNetworkTransaction::OnIOComplete)), 31 user_callback_(NULL), 32 user_buffer_len_(0), 33 session_(session), 34 request_(NULL), 35 next_state_(STATE_NONE), 36 stream_(NULL) { 37 } 38 39 FlipNetworkTransaction::~FlipNetworkTransaction() { 40 LOG(INFO) << "FlipNetworkTransaction dead. " << this; 41 if (stream_.get()) 42 stream_->Cancel(); 43 } 44 45 int FlipNetworkTransaction::Start(const HttpRequestInfo* request_info, 46 CompletionCallback* callback, 47 LoadLog* load_log) { 48 CHECK(request_info); 49 CHECK(callback); 50 51 SIMPLE_STATS_COUNTER("FlipNetworkTransaction.Count"); 52 53 load_log_ = load_log; 54 request_ = request_info; 55 start_time_ = base::TimeTicks::Now(); 56 57 next_state_ = STATE_INIT_CONNECTION; 58 int rv = DoLoop(OK); 59 if (rv == ERR_IO_PENDING) 60 user_callback_ = callback; 61 return rv; 62 } 63 64 int FlipNetworkTransaction::RestartIgnoringLastError( 65 CompletionCallback* callback) { 66 // TODO(mbelshe): implement me. 67 NOTIMPLEMENTED(); 68 return ERR_NOT_IMPLEMENTED; 69 } 70 71 int FlipNetworkTransaction::RestartWithCertificate( 72 X509Certificate* client_cert, CompletionCallback* callback) { 73 // TODO(mbelshe): implement me. 74 NOTIMPLEMENTED(); 75 return ERR_NOT_IMPLEMENTED; 76 } 77 78 int FlipNetworkTransaction::RestartWithAuth( 79 const std::wstring& username, 80 const std::wstring& password, 81 CompletionCallback* callback) { 82 // TODO(mbelshe): implement me. 83 NOTIMPLEMENTED(); 84 return 0; 85 } 86 87 int FlipNetworkTransaction::Read(IOBuffer* buf, int buf_len, 88 CompletionCallback* callback) { 89 DCHECK(buf); 90 DCHECK_GT(buf_len, 0); 91 DCHECK(callback); 92 93 user_buffer_ = buf; 94 user_buffer_len_ = buf_len; 95 96 next_state_ = STATE_READ_BODY; 97 int rv = DoLoop(OK); 98 if (rv == ERR_IO_PENDING) 99 user_callback_ = callback; 100 return rv; 101 } 102 103 const HttpResponseInfo* FlipNetworkTransaction::GetResponseInfo() const { 104 return (response_.headers || response_.ssl_info.cert) ? &response_ : NULL; 105 } 106 107 LoadState FlipNetworkTransaction::GetLoadState() const { 108 switch (next_state_) { 109 case STATE_INIT_CONNECTION_COMPLETE: 110 if (flip_.get()) 111 return flip_->GetLoadState(); 112 return LOAD_STATE_CONNECTING; 113 case STATE_SEND_REQUEST_COMPLETE: 114 return LOAD_STATE_SENDING_REQUEST; 115 case STATE_READ_HEADERS_COMPLETE: 116 return LOAD_STATE_WAITING_FOR_RESPONSE; 117 case STATE_READ_BODY_COMPLETE: 118 return LOAD_STATE_READING_RESPONSE; 119 default: 120 return LOAD_STATE_IDLE; 121 } 122 } 123 124 uint64 FlipNetworkTransaction::GetUploadProgress() const { 125 if (!stream_.get()) 126 return 0; 127 128 return stream_->GetUploadProgress(); 129 } 130 131 void FlipNetworkTransaction::DoCallback(int rv) { 132 CHECK(rv != ERR_IO_PENDING); 133 CHECK(user_callback_); 134 135 // Since Run may result in Read being called, clear user_callback_ up front. 136 CompletionCallback* c = user_callback_; 137 user_callback_ = NULL; 138 c->Run(rv); 139 } 140 141 void FlipNetworkTransaction::OnIOComplete(int result) { 142 int rv = DoLoop(result); 143 if (rv != ERR_IO_PENDING) 144 DoCallback(rv); 145 } 146 147 int FlipNetworkTransaction::DoLoop(int result) { 148 DCHECK(next_state_ != STATE_NONE); 149 DCHECK(request_); 150 151 if (!request_) 152 return 0; 153 154 int rv = result; 155 do { 156 State state = next_state_; 157 next_state_ = STATE_NONE; 158 switch (state) { 159 case STATE_INIT_CONNECTION: 160 DCHECK_EQ(OK, rv); 161 LoadLog::BeginEvent(load_log_, 162 LoadLog::TYPE_FLIP_TRANSACTION_INIT_CONNECTION); 163 rv = DoInitConnection(); 164 break; 165 case STATE_INIT_CONNECTION_COMPLETE: 166 LoadLog::EndEvent(load_log_, 167 LoadLog::TYPE_FLIP_TRANSACTION_INIT_CONNECTION); 168 rv = DoInitConnectionComplete(rv); 169 break; 170 case STATE_SEND_REQUEST: 171 DCHECK_EQ(OK, rv); 172 LoadLog::BeginEvent(load_log_, 173 LoadLog::TYPE_FLIP_TRANSACTION_SEND_REQUEST); 174 rv = DoSendRequest(); 175 break; 176 case STATE_SEND_REQUEST_COMPLETE: 177 LoadLog::EndEvent(load_log_, 178 LoadLog::TYPE_FLIP_TRANSACTION_SEND_REQUEST); 179 rv = DoSendRequestComplete(rv); 180 break; 181 case STATE_READ_HEADERS: 182 DCHECK_EQ(OK, rv); 183 LoadLog::BeginEvent(load_log_, 184 LoadLog::TYPE_FLIP_TRANSACTION_READ_HEADERS); 185 rv = DoReadHeaders(); 186 break; 187 case STATE_READ_HEADERS_COMPLETE: 188 LoadLog::EndEvent(load_log_, 189 LoadLog::TYPE_FLIP_TRANSACTION_READ_HEADERS); 190 rv = DoReadHeadersComplete(rv); 191 break; 192 case STATE_READ_BODY: 193 DCHECK_EQ(OK, rv); 194 LoadLog::BeginEvent(load_log_, 195 LoadLog::TYPE_FLIP_TRANSACTION_READ_BODY); 196 rv = DoReadBody(); 197 break; 198 case STATE_READ_BODY_COMPLETE: 199 LoadLog::EndEvent(load_log_, 200 LoadLog::TYPE_FLIP_TRANSACTION_READ_BODY); 201 rv = DoReadBodyComplete(rv); 202 break; 203 case STATE_NONE: 204 rv = ERR_FAILED; 205 break; 206 default: 207 NOTREACHED() << "bad state"; 208 rv = ERR_FAILED; 209 break; 210 } 211 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 212 213 return rv; 214 } 215 216 int FlipNetworkTransaction::DoInitConnection() { 217 next_state_ = STATE_INIT_CONNECTION_COMPLETE; 218 219 std::string host = request_->url.HostNoBrackets(); 220 int port = request_->url.EffectiveIntPort(); 221 222 // Use the fixed testing ports if they've been provided. This is useful for 223 // debugging. 224 if (FlipSession::SSLMode()) { 225 if (session_->fixed_https_port() != 0) 226 port = session_->fixed_https_port(); 227 } else if (session_->fixed_http_port() != 0) { 228 port = session_->fixed_http_port(); 229 } 230 231 std::string connection_group = "flip."; 232 connection_group.append(host); 233 234 HostResolver::RequestInfo resolve_info(host, port); 235 236 flip_ = session_->flip_session_pool()->Get(resolve_info, session_); 237 DCHECK(flip_); 238 239 return flip_->Connect( 240 connection_group, resolve_info, request_->priority, load_log_); 241 } 242 243 int FlipNetworkTransaction::DoInitConnectionComplete(int result) { 244 if (result < 0) 245 return result; 246 247 next_state_ = STATE_SEND_REQUEST; 248 return OK; 249 } 250 251 int FlipNetworkTransaction::DoSendRequest() { 252 next_state_ = STATE_SEND_REQUEST_COMPLETE; 253 CHECK(!stream_.get()); 254 UploadDataStream* upload_data = request_->upload_data ? 255 new UploadDataStream(request_->upload_data) : NULL; 256 stream_ = flip_->GetOrCreateStream(*request_, upload_data, load_log_.get()); 257 // Release the reference to |flip_| since we don't need it anymore. 258 flip_ = NULL; 259 return stream_->SendRequest(upload_data, &response_, &io_callback_); 260 } 261 262 int FlipNetworkTransaction::DoSendRequestComplete(int result) { 263 if (result < 0) 264 return result; 265 266 next_state_ = STATE_READ_HEADERS; 267 return OK; 268 } 269 270 int FlipNetworkTransaction::DoReadHeaders() { 271 next_state_ = STATE_READ_HEADERS_COMPLETE; 272 return stream_->ReadResponseHeaders(&io_callback_); 273 } 274 275 int FlipNetworkTransaction::DoReadHeadersComplete(int result) { 276 // TODO(willchan): Flesh out the support for HTTP authentication here. 277 return result; 278 } 279 280 int FlipNetworkTransaction::DoReadBody() { 281 next_state_ = STATE_READ_BODY_COMPLETE; 282 283 return stream_->ReadResponseBody( 284 user_buffer_, user_buffer_len_, &io_callback_); 285 } 286 287 int FlipNetworkTransaction::DoReadBodyComplete(int result) { 288 user_buffer_ = NULL; 289 user_buffer_len_ = 0; 290 291 if (result <= 0) 292 stream_ = NULL; 293 294 return result; 295 } 296 297 } // namespace net 298