Home | History | Annotate | Download | only in flip
      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