1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
#include "talk/base/common.h"
#include "talk/base/firewallsocketserver.h"
#include "talk/base/httpclient.h"
#include "talk/base/logging.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/socketadapters.h"
#include "talk/base/socketpool.h"
#include "talk/base/ssladapter.h"
#include "talk/base/asynchttprequest.h"
using namespace talk_base;
///////////////////////////////////////////////////////////////////////////////
// HttpMonitor
///////////////////////////////////////////////////////////////////////////////
HttpMonitor::HttpMonitor(SocketServer *ss) {
ASSERT(talk_base::Thread::Current() != NULL);
ss_ = ss;
reset();
}
void HttpMonitor::Connect(talk_base::HttpClient *http) {
http->SignalHttpClientComplete.connect(this,
&HttpMonitor::OnHttpClientComplete);
}
void HttpMonitor::OnHttpClientComplete(talk_base::HttpClient * http, int err) {
complete_ = true;
err_ = err;
ss_->WakeUp();
}
///////////////////////////////////////////////////////////////////////////////
// SslSocketFactory
///////////////////////////////////////////////////////////////////////////////
talk_base::Socket * SslSocketFactory::CreateSocket(int type) {
return factory_->CreateSocket(type);
}
talk_base::AsyncSocket * SslSocketFactory::CreateAsyncSocket(int type) {
talk_base::AsyncSocket * socket = factory_->CreateAsyncSocket(type);
if (!socket)
return 0;
// Binary logging happens at the lowest level
if (!logging_label_.empty() && binary_mode_) {
socket = new talk_base::LoggingSocketAdapter(socket, logging_level_,
logging_label_.c_str(),
binary_mode_);
}
if (proxy_.type) {
talk_base::AsyncSocket * proxy_socket = 0;
if (proxy_.type == talk_base::PROXY_SOCKS5) {
proxy_socket = new talk_base::AsyncSocksProxySocket(socket, proxy_.address,
proxy_.username, proxy_.password);
} else {
// Note: we are trying unknown proxies as HTTPS currently
proxy_socket = new talk_base::AsyncHttpsProxySocket(socket,
agent_, proxy_.address,
proxy_.username, proxy_.password);
}
if (!proxy_socket) {
delete socket;
return 0;
}
socket = proxy_socket; // for our purposes the proxy is now the socket
}
if (!hostname_.empty()) {
talk_base::SSLAdapter * ssl_adapter = talk_base::SSLAdapter::Create(socket);
ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_);
ssl_adapter->StartSSL(hostname_.c_str(), true);
socket = ssl_adapter;
}
// Regular logging occurs at the highest level
if (!logging_label_.empty() && !binary_mode_) {
socket = new talk_base::LoggingSocketAdapter(socket, logging_level_,
logging_label_.c_str(),
binary_mode_);
}
return socket;
}
///////////////////////////////////////////////////////////////////////////////
// AsyncHttpRequest
///////////////////////////////////////////////////////////////////////////////
const int kDefaultHTTPTimeout = 30 * 1000; // 30 sec
AsyncHttpRequest::AsyncHttpRequest(const std::string &user_agent)
: firewall_(0), port_(80), secure_(false),
timeout_(kDefaultHTTPTimeout), fail_redirect_(false),
client_(user_agent.c_str(), NULL)
{
}
void AsyncHttpRequest::DoWork() {
// TODO: Rewrite this to use the thread's native socket server, and a more
// natural flow?
talk_base::PhysicalSocketServer physical;
talk_base::SocketServer * ss = &physical;
if (firewall_) {
ss = new talk_base::FirewallSocketServer(ss, firewall_);
}
SslSocketFactory factory(ss, client_.agent());
factory.SetProxy(proxy_);
if (secure_)
factory.UseSSL(host_.c_str());
//factory.SetLogging("AsyncHttpRequest");
talk_base::ReuseSocketPool pool(&factory);
client_.set_pool(&pool);
bool transparent_proxy = (port_ == 80)
&& ((proxy_.type == talk_base::PROXY_HTTPS)
|| (proxy_.type == talk_base::PROXY_UNKNOWN));
if (transparent_proxy) {
client_.set_proxy(proxy_);
}
client_.set_fail_redirect(fail_redirect_);
talk_base::SocketAddress server(host_, port_);
client_.set_server(server);
HttpMonitor monitor(ss);
monitor.Connect(&client_);
client_.start();
ss->Wait(timeout_, true);
if (!monitor.done()) {
LOG(LS_INFO) << "AsyncHttpRequest request timed out";
client_.reset();
return;
}
if (monitor.error()) {
LOG(LS_INFO) << "AsyncHttpRequest request error: " << monitor.error();
if (monitor.error() == talk_base::HE_AUTH) {
//proxy_auth_required_ = true;
}
return;
}
std::string value;
if (client_.response().hasHeader(HH_LOCATION, &value)) {
response_redirect_ = value.c_str();
}
}
|