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();
}
}
|