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