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