Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/base/asynchttprequest.h"
     12 
     13 namespace rtc {
     14 
     15 enum {
     16   MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
     17   MSG_LAUNCH_REQUEST
     18 };
     19 static const int kDefaultHTTPTimeout = 30 * 1000;  // 30 sec
     20 
     21 ///////////////////////////////////////////////////////////////////////////////
     22 // AsyncHttpRequest
     23 ///////////////////////////////////////////////////////////////////////////////
     24 
     25 AsyncHttpRequest::AsyncHttpRequest(const std::string &user_agent)
     26     : start_delay_(0),
     27       firewall_(NULL),
     28       port_(80),
     29       secure_(false),
     30       timeout_(kDefaultHTTPTimeout),
     31       fail_redirect_(false),
     32       factory_(Thread::Current()->socketserver(), user_agent),
     33       pool_(&factory_),
     34       client_(user_agent.c_str(), &pool_),
     35       error_(HE_NONE) {
     36   client_.SignalHttpClientComplete.connect(this,
     37       &AsyncHttpRequest::OnComplete);
     38 }
     39 
     40 AsyncHttpRequest::~AsyncHttpRequest() {
     41 }
     42 
     43 void AsyncHttpRequest::OnWorkStart() {
     44   if (start_delay_ <= 0) {
     45     LaunchRequest();
     46   } else {
     47     Thread::Current()->PostDelayed(start_delay_, this, MSG_LAUNCH_REQUEST);
     48   }
     49 }
     50 
     51 void AsyncHttpRequest::OnWorkStop() {
     52   // worker is already quitting, no need to explicitly quit
     53   LOG(LS_INFO) << "HttpRequest cancelled";
     54 }
     55 
     56 void AsyncHttpRequest::OnComplete(HttpClient* client, HttpErrorType error) {
     57   Thread::Current()->Clear(this, MSG_TIMEOUT);
     58 
     59   set_error(error);
     60   if (!error) {
     61     LOG(LS_INFO) << "HttpRequest completed successfully";
     62 
     63     std::string value;
     64     if (client_.response().hasHeader(HH_LOCATION, &value)) {
     65       response_redirect_ = value.c_str();
     66     }
     67   } else {
     68     LOG(LS_INFO) << "HttpRequest completed with error: " << error;
     69   }
     70 
     71   worker()->Quit();
     72 }
     73 
     74 void AsyncHttpRequest::OnMessage(Message* message) {
     75   switch (message->message_id) {
     76    case MSG_TIMEOUT:
     77     LOG(LS_INFO) << "HttpRequest timed out";
     78     client_.reset();
     79     worker()->Quit();
     80     break;
     81    case MSG_LAUNCH_REQUEST:
     82     LaunchRequest();
     83     break;
     84    default:
     85     SignalThread::OnMessage(message);
     86     break;
     87   }
     88 }
     89 
     90 void AsyncHttpRequest::DoWork() {
     91   // Do nothing while we wait for the request to finish. We only do this so
     92   // that we can be a SignalThread; in the future this class should not be
     93   // a SignalThread, since it does not need to spawn a new thread.
     94   Thread::Current()->ProcessMessages(kForever);
     95 }
     96 
     97 void AsyncHttpRequest::LaunchRequest() {
     98   factory_.SetProxy(proxy_);
     99   if (secure_)
    100     factory_.UseSSL(host_.c_str());
    101 
    102   bool transparent_proxy = (port_ == 80) &&
    103            ((proxy_.type == PROXY_HTTPS) || (proxy_.type == PROXY_UNKNOWN));
    104   if (transparent_proxy) {
    105     client_.set_proxy(proxy_);
    106   }
    107   client_.set_fail_redirect(fail_redirect_);
    108   client_.set_server(SocketAddress(host_, port_));
    109 
    110   LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path;
    111 
    112   Thread::Current()->PostDelayed(timeout_, this, MSG_TIMEOUT);
    113   client_.start();
    114 }
    115 
    116 }  // namespace rtc
    117