blob: 84dae0e535857d02db30ee9d44484c2d6923159e [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
11#include "webrtc/base/autodetectproxy.h"
12#include "webrtc/base/httpcommon.h"
13#include "webrtc/base/httpcommon-inl.h"
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +000014#include "webrtc/base/scoped_ptr.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000015#include "webrtc/base/socketadapters.h"
16#include "webrtc/base/ssladapter.h"
17#include "webrtc/base/sslsocketfactory.h"
18
19namespace 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
28class ProxySocketAdapter : public AsyncSocketAdapter {
29 public:
30 ProxySocketAdapter(SslSocketFactory* factory, int family, int type)
31 : AsyncSocketAdapter(NULL), factory_(factory), family_(family),
32 type_(type), detect_(NULL) {
33 }
34 virtual ~ProxySocketAdapter() {
35 Close();
36 }
37
38 virtual int Connect(const SocketAddress& addr) {
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 }
54 virtual int GetError() const {
55 if (socket_) {
56 return socket_->GetError();
57 }
58 return detect_ ? EWOULDBLOCK : EADDRNOTAVAIL;
59 }
60 virtual int Close() {
61 if (socket_) {
62 return socket_->Close();
63 }
64 if (detect_) {
65 detect_->Destroy(false);
66 detect_ = NULL;
67 }
68 return 0;
69 }
70 virtual ConnState GetState() const {
71 if (socket_) {
72 return socket_->GetState();
73 }
74 return detect_ ? CS_CONNECTING : CS_CLOSED;
75 }
76
77private:
78 // AutoDetectProxy Slots
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
102Socket* SslSocketFactory::CreateSocket(int type) {
103 return CreateSocket(AF_INET, type);
104}
105
106Socket* SslSocketFactory::CreateSocket(int family, int type) {
107 return factory_->CreateSocket(family, type);
108}
109
110AsyncSocket* SslSocketFactory::CreateAsyncSocket(int type) {
111 return CreateAsyncSocket(AF_INET, type);
112}
113
114AsyncSocket* SslSocketFactory::CreateAsyncSocket(int family, int type) {
115 if (autodetect_proxy_) {
116 return new ProxySocketAdapter(this, family, type);
117 } else {
118 return CreateProxySocket(proxy_, family, type);
119 }
120}
121
122
123AsyncSocket* SslSocketFactory::CreateProxySocket(const ProxyInfo& proxy,
124 int family,
125 int type) {
126 AsyncSocket* socket = factory_->CreateAsyncSocket(family, type);
127 if (!socket)
128 return NULL;
129
130 // Binary logging happens at the lowest level
131 if (!logging_label_.empty() && binary_mode_) {
132 socket = new LoggingSocketAdapter(socket, logging_level_,
133 logging_label_.c_str(), binary_mode_);
134 }
135
136 if (proxy.type) {
137 AsyncSocket* proxy_socket = 0;
138 if (proxy_.type == PROXY_SOCKS5) {
139 proxy_socket = new AsyncSocksProxySocket(socket, proxy.address,
140 proxy.username, proxy.password);
141 } else {
142 // Note: we are trying unknown proxies as HTTPS currently
143 AsyncHttpsProxySocket* http_proxy =
144 new AsyncHttpsProxySocket(socket, agent_, proxy.address,
145 proxy.username, proxy.password);
146 http_proxy->SetForceConnect(force_connect_ || !hostname_.empty());
147 proxy_socket = http_proxy;
148 }
149 if (!proxy_socket) {
150 delete socket;
151 return NULL;
152 }
153 socket = proxy_socket; // for our purposes the proxy is now the socket
154 }
155
156 if (!hostname_.empty()) {
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +0000157 rtc::scoped_ptr<SSLAdapter> ssl_adapter(SSLAdapter::Create(socket));
158 if (!ssl_adapter) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000159 LOG_F(LS_ERROR) << "SSL unavailable";
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +0000160 delete socket;
161 return NULL;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000162 }
pthatcher@webrtc.org69472e72015-01-07 18:01:07 +0000163
164 ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_);
165 if (ssl_adapter->StartSSL(hostname_.c_str(), true) != 0) {
166 LOG_F(LS_ERROR) << "SSL failed to start.";
167 return NULL;
168 }
169 socket = ssl_adapter.release();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000170 }
171
172 // Regular logging occurs at the highest level
173 if (!logging_label_.empty() && !binary_mode_) {
174 socket = new LoggingSocketAdapter(socket, logging_level_,
175 logging_label_.c_str(), binary_mode_);
176 }
177 return socket;
178}
179
180///////////////////////////////////////////////////////////////////////////////
181
182} // namespace rtc