blob: 7ab58fd04c6f53177bd1c47a2c66e439e0e93559 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2007 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
jbauch555604a2016-04-26 03:13:22 -070011#include <memory>
12
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013#include "webrtc/base/autodetectproxy.h"
14#include "webrtc/base/httpcommon.h"
15#include "webrtc/base/httpcommon-inl.h"
16#include "webrtc/base/socketadapters.h"
17#include "webrtc/base/ssladapter.h"
18#include "webrtc/base/sslsocketfactory.h"
19
20namespace rtc {
21
22///////////////////////////////////////////////////////////////////////////////
23// ProxySocketAdapter
24// TODO: Consider combining AutoDetectProxy and ProxySocketAdapter. I think
25// the socket adapter is the more appropriate idiom for automatic proxy
26// detection. We may or may not want to combine proxydetect.* as well.
27///////////////////////////////////////////////////////////////////////////////
28
29class ProxySocketAdapter : public AsyncSocketAdapter {
30 public:
31 ProxySocketAdapter(SslSocketFactory* factory, int family, int type)
32 : AsyncSocketAdapter(NULL), factory_(factory), family_(family),
33 type_(type), detect_(NULL) {
34 }
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000035 ~ProxySocketAdapter() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000036 Close();
37 }
38
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000039 int Connect(const SocketAddress& addr) override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040 ASSERT(NULL == detect_);
41 ASSERT(NULL == socket_);
42 remote_ = addr;
43 if (remote_.IsAnyIP() && remote_.hostname().empty()) {
44 LOG_F(LS_ERROR) << "Empty address";
45 return SOCKET_ERROR;
46 }
47 Url<char> url("/", remote_.HostAsURIString(), remote_.port());
48 detect_ = new AutoDetectProxy(factory_->agent_);
49 detect_->set_server_url(url.url());
50 detect_->SignalWorkDone.connect(this,
51 &ProxySocketAdapter::OnProxyDetectionComplete);
52 detect_->Start();
53 return SOCKET_ERROR;
54 }
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000055 int GetError() const override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056 if (socket_) {
57 return socket_->GetError();
58 }
59 return detect_ ? EWOULDBLOCK : EADDRNOTAVAIL;
60 }
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000061 int Close() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062 if (socket_) {
63 return socket_->Close();
64 }
65 if (detect_) {
66 detect_->Destroy(false);
67 detect_ = NULL;
68 }
69 return 0;
70 }
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000071 ConnState GetState() const override {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000072 if (socket_) {
73 return socket_->GetState();
74 }
75 return detect_ ? CS_CONNECTING : CS_CLOSED;
76 }
77
78private:
79 // AutoDetectProxy Slots
80 void OnProxyDetectionComplete(SignalThread* thread) {
81 ASSERT(detect_ == thread);
82 Attach(factory_->CreateProxySocket(detect_->proxy(), family_, type_));
83 detect_->Release();
84 detect_ = NULL;
85 if (0 == AsyncSocketAdapter::Connect(remote_)) {
86 SignalConnectEvent(this);
87 } else if (!IsBlockingError(socket_->GetError())) {
88 SignalCloseEvent(this, socket_->GetError());
89 }
90 }
91
92 SslSocketFactory* factory_;
93 int family_;
94 int type_;
95 SocketAddress remote_;
96 AutoDetectProxy* detect_;
97};
98
99///////////////////////////////////////////////////////////////////////////////
100// SslSocketFactory
101///////////////////////////////////////////////////////////////////////////////
102
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000103SslSocketFactory::SslSocketFactory(SocketFactory* factory,
104 const std::string& user_agent)
105 : factory_(factory),
106 agent_(user_agent),
107 autodetect_proxy_(true),
108 force_connect_(false),
109 logging_level_(LS_VERBOSE),
110 binary_mode_(false),
111 ignore_bad_cert_(false) {
112}
113
114SslSocketFactory::~SslSocketFactory() = default;
115
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116Socket* SslSocketFactory::CreateSocket(int type) {
117 return CreateSocket(AF_INET, type);
118}
119
120Socket* SslSocketFactory::CreateSocket(int family, int type) {
121 return factory_->CreateSocket(family, type);
122}
123
124AsyncSocket* SslSocketFactory::CreateAsyncSocket(int type) {
125 return CreateAsyncSocket(AF_INET, type);
126}
127
128AsyncSocket* SslSocketFactory::CreateAsyncSocket(int family, int type) {
129 if (autodetect_proxy_) {
130 return new ProxySocketAdapter(this, family, type);
131 } else {
132 return CreateProxySocket(proxy_, family, type);
133 }
134}
135
136
137AsyncSocket* SslSocketFactory::CreateProxySocket(const ProxyInfo& proxy,
138 int family,
139 int type) {
140 AsyncSocket* socket = factory_->CreateAsyncSocket(family, type);
141 if (!socket)
142 return NULL;
143
144 // Binary logging happens at the lowest level
145 if (!logging_label_.empty() && binary_mode_) {
146 socket = new LoggingSocketAdapter(socket, logging_level_,
147 logging_label_.c_str(), binary_mode_);
148 }
149
150 if (proxy.type) {
151 AsyncSocket* proxy_socket = 0;
152 if (proxy_.type == PROXY_SOCKS5) {
153 proxy_socket = new AsyncSocksProxySocket(socket, proxy.address,
154 proxy.username, proxy.password);
155 } else {
156 // Note: we are trying unknown proxies as HTTPS currently
157 AsyncHttpsProxySocket* http_proxy =
158 new AsyncHttpsProxySocket(socket, agent_, proxy.address,
159 proxy.username, proxy.password);
160 http_proxy->SetForceConnect(force_connect_ || !hostname_.empty());
161 proxy_socket = http_proxy;
162 }
163 if (!proxy_socket) {
164 delete socket;
165 return NULL;
166 }
167 socket = proxy_socket; // for our purposes the proxy is now the socket
168 }
169
170 if (!hostname_.empty()) {
jbauch555604a2016-04-26 03:13:22 -0700171 std::unique_ptr<SSLAdapter> ssl_adapter(SSLAdapter::Create(socket));
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +0000172 if (!ssl_adapter) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000173 LOG_F(LS_ERROR) << "SSL unavailable";
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +0000174 delete socket;
175 return NULL;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000176 }
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +0000177
178 ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_);
179 if (ssl_adapter->StartSSL(hostname_.c_str(), true) != 0) {
180 LOG_F(LS_ERROR) << "SSL failed to start.";
181 return NULL;
182 }
183 socket = ssl_adapter.release();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000184 }
185
186 // Regular logging occurs at the highest level
187 if (!logging_label_.empty() && !binary_mode_) {
188 socket = new LoggingSocketAdapter(socket, logging_level_,
189 logging_label_.c_str(), binary_mode_);
190 }
191 return socket;
192}
193
194///////////////////////////////////////////////////////////////////////////////
195
196} // namespace rtc