|  | /* | 
|  | *  Copyright 2006 The WebRTC Project Authors. All rights reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "webrtc/base/httprequest.h" | 
|  |  | 
|  | #include "webrtc/base/common.h" | 
|  | #include "webrtc/base/firewallsocketserver.h" | 
|  | #include "webrtc/base/httpclient.h" | 
|  | #include "webrtc/base/logging.h" | 
|  | #include "webrtc/base/physicalsocketserver.h" | 
|  | #include "webrtc/base/socketadapters.h" | 
|  | #include "webrtc/base/socketpool.h" | 
|  | #include "webrtc/base/ssladapter.h" | 
|  |  | 
|  | using namespace rtc; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // HttpMonitor | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | HttpMonitor::HttpMonitor(SocketServer *ss) { | 
|  | ASSERT(Thread::Current() != NULL); | 
|  | ss_ = ss; | 
|  | reset(); | 
|  | } | 
|  |  | 
|  | void HttpMonitor::Connect(HttpClient *http) { | 
|  | http->SignalHttpClientComplete.connect(this, | 
|  | &HttpMonitor::OnHttpClientComplete); | 
|  | } | 
|  |  | 
|  | void HttpMonitor::OnHttpClientComplete(HttpClient * http, HttpErrorType error) { | 
|  | complete_ = true; | 
|  | error_ = error; | 
|  | ss_->WakeUp(); | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // HttpRequest | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | const int kDefaultHTTPTimeout = 30 * 1000; // 30 sec | 
|  |  | 
|  | HttpRequest::HttpRequest(const std::string &user_agent) | 
|  | : firewall_(0), port_(80), secure_(false), | 
|  | timeout_(kDefaultHTTPTimeout), fail_redirect_(false), | 
|  | client_(user_agent.c_str(), NULL), error_(HE_NONE) { | 
|  | } | 
|  |  | 
|  | void HttpRequest::Send() { | 
|  | // TODO: Rewrite this to use the thread's native socket server, and a more | 
|  | // natural flow? | 
|  |  | 
|  | PhysicalSocketServer physical; | 
|  | SocketServer * ss = &physical; | 
|  | if (firewall_) { | 
|  | ss = new FirewallSocketServer(ss, firewall_); | 
|  | } | 
|  |  | 
|  | SslSocketFactory factory(ss, client_.agent()); | 
|  | factory.SetProxy(proxy_); | 
|  | if (secure_) | 
|  | factory.UseSSL(host_.c_str()); | 
|  |  | 
|  | //factory.SetLogging("HttpRequest"); | 
|  |  | 
|  | ReuseSocketPool pool(&factory); | 
|  | client_.set_pool(&pool); | 
|  |  | 
|  | bool transparent_proxy = (port_ == 80) && ((proxy_.type == PROXY_HTTPS) || | 
|  | (proxy_.type == PROXY_UNKNOWN)); | 
|  |  | 
|  | if (transparent_proxy) { | 
|  | client_.set_proxy(proxy_); | 
|  | } | 
|  | client_.set_fail_redirect(fail_redirect_); | 
|  |  | 
|  | SocketAddress server(host_, port_); | 
|  | client_.set_server(server); | 
|  |  | 
|  | LOG(LS_INFO) << "HttpRequest start: " << host_ + client_.request().path; | 
|  |  | 
|  | HttpMonitor monitor(ss); | 
|  | monitor.Connect(&client_); | 
|  | client_.start(); | 
|  | ss->Wait(timeout_, true); | 
|  | if (!monitor.done()) { | 
|  | LOG(LS_INFO) << "HttpRequest request timed out"; | 
|  | client_.reset(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | set_error(monitor.error()); | 
|  | if (error_) { | 
|  | LOG(LS_INFO) << "HttpRequest request error: " << error_; | 
|  | return; | 
|  | } | 
|  |  | 
|  | std::string value; | 
|  | if (client_.response().hasHeader(HH_LOCATION, &value)) { | 
|  | response_redirect_ = value.c_str(); | 
|  | } | 
|  | } |