1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/*
2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Copyright 2007 The WebRTC Project Authors. All rights reserved.
3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *
4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */
10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/autodetectproxy.h"
12f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/httpcommon.h"
13f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/httpcommon-inl.h"
1469472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org#include "webrtc/base/scoped_ptr.h"
15f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/socketadapters.h"
16f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/ssladapter.h"
17f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/sslsocketfactory.h"
18f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
19f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgnamespace rtc {
20f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// ProxySocketAdapter
23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// TODO: Consider combining AutoDetectProxy and ProxySocketAdapter.  I think
24f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// the socket adapter is the more appropriate idiom for automatic proxy
25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// detection.  We may or may not want to combine proxydetect.* as well.
26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgclass ProxySocketAdapter : public AsyncSocketAdapter {
29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org public:
30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ProxySocketAdapter(SslSocketFactory* factory, int family, int type)
31f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      : AsyncSocketAdapter(NULL), factory_(factory), family_(family),
32f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        type_(type), detect_(NULL) {
33f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
3467186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org  ~ProxySocketAdapter() override {
35f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Close();
36f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
37f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
3867186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org  int Connect(const SocketAddress& addr) override {
39f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT(NULL == detect_);
40f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT(NULL == socket_);
41f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    remote_ = addr;
42f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (remote_.IsAnyIP() && remote_.hostname().empty()) {
43f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG_F(LS_ERROR) << "Empty address";
44f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return SOCKET_ERROR;
45f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
46f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Url<char> url("/", remote_.HostAsURIString(), remote_.port());
47f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    detect_ = new AutoDetectProxy(factory_->agent_);
48f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    detect_->set_server_url(url.url());
49f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    detect_->SignalWorkDone.connect(this,
50f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org        &ProxySocketAdapter::OnProxyDetectionComplete);
51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    detect_->Start();
52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return SOCKET_ERROR;
53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
5467186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org  int GetError() const override {
55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (socket_) {
56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return socket_->GetError();
57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
58f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return detect_ ? EWOULDBLOCK : EADDRNOTAVAIL;
59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
6067186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org  int Close() override {
61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (socket_) {
62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return socket_->Close();
63f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
64f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (detect_) {
65f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      detect_->Destroy(false);
66f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      detect_ = NULL;
67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
68f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return 0;
69f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
7067186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org  ConnState GetState() const override {
71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (socket_) {
72f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return socket_->GetState();
73f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
74f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return detect_ ? CS_CONNECTING : CS_CLOSED;
75f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
76f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
77f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgprivate:
78f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // AutoDetectProxy Slots
79f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  void OnProxyDetectionComplete(SignalThread* thread) {
80f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ASSERT(detect_ == thread);
81f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    Attach(factory_->CreateProxySocket(detect_->proxy(), family_, type_));
82f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    detect_->Release();
83f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    detect_ = NULL;
84f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (0 == AsyncSocketAdapter::Connect(remote_)) {
85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      SignalConnectEvent(this);
86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    } else if (!IsBlockingError(socket_->GetError())) {
87f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      SignalCloseEvent(this, socket_->GetError());
88f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
89f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
91f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SslSocketFactory* factory_;
92f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int family_;
93f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  int type_;
94f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  SocketAddress remote_;
95f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AutoDetectProxy* detect_;
96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org};
97f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
98f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
99f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// SslSocketFactory
100f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
101f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
10267186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.orgSslSocketFactory::SslSocketFactory(SocketFactory* factory,
10367186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org                                   const std::string& user_agent)
10467186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org    : factory_(factory),
10567186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org      agent_(user_agent),
10667186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org      autodetect_proxy_(true),
10767186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org      force_connect_(false),
10867186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org      logging_level_(LS_VERBOSE),
10967186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org      binary_mode_(false),
11067186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org      ignore_bad_cert_(false) {
11167186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org}
11267186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org
11367186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.orgSslSocketFactory::~SslSocketFactory() = default;
11467186fe00cc68cbe03aa66d17fb4962458ca96d2kwiberg@webrtc.org
115f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocket* SslSocketFactory::CreateSocket(int type) {
116f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return CreateSocket(AF_INET, type);
117f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
118f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
119f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgSocket* SslSocketFactory::CreateSocket(int family, int type) {
120f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return factory_->CreateSocket(family, type);
121f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
122f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
123f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncSocket* SslSocketFactory::CreateAsyncSocket(int type) {
124f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return CreateAsyncSocket(AF_INET, type);
125f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
126f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
127f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncSocket* SslSocketFactory::CreateAsyncSocket(int family, int type) {
128f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (autodetect_proxy_) {
129f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return new ProxySocketAdapter(this, family, type);
130f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
131f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return CreateProxySocket(proxy_, family, type);
132f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
133f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
134f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
135f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
136f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgAsyncSocket* SslSocketFactory::CreateProxySocket(const ProxyInfo& proxy,
137f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                                 int family,
138f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                                 int type) {
139f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  AsyncSocket* socket = factory_->CreateAsyncSocket(family, type);
140f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!socket)
141f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return NULL;
142f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
143f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Binary logging happens at the lowest level
144f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!logging_label_.empty() && binary_mode_) {
145f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    socket = new LoggingSocketAdapter(socket, logging_level_,
146f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                      logging_label_.c_str(), binary_mode_);
147f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
148f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
149f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (proxy.type) {
150f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    AsyncSocket* proxy_socket = 0;
151f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (proxy_.type == PROXY_SOCKS5) {
152f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      proxy_socket = new AsyncSocksProxySocket(socket, proxy.address,
153f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                               proxy.username, proxy.password);
154f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    } else {
155f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      // Note: we are trying unknown proxies as HTTPS currently
156f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      AsyncHttpsProxySocket* http_proxy =
157f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org          new AsyncHttpsProxySocket(socket, agent_, proxy.address,
158f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                    proxy.username, proxy.password);
159f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      http_proxy->SetForceConnect(force_connect_ || !hostname_.empty());
160f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      proxy_socket = http_proxy;
161f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
162f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (!proxy_socket) {
163f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      delete socket;
164f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return NULL;
165f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
166f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    socket = proxy_socket;  // for our purposes the proxy is now the socket
167f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
168f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
169f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!hostname_.empty()) {
17069472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org    rtc::scoped_ptr<SSLAdapter> ssl_adapter(SSLAdapter::Create(socket));
17169472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org    if (!ssl_adapter) {
172f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG_F(LS_ERROR) << "SSL unavailable";
17369472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org      delete socket;
17469472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org      return NULL;
17569472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org    }
17669472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org
17769472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org    ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_);
17869472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org    if (ssl_adapter->StartSSL(hostname_.c_str(), true) != 0) {
17969472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org      LOG_F(LS_ERROR) << "SSL failed to start.";
18069472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org      return NULL;
181f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
18269472e711c1162d6dfa31664cb98bee3f9247d97pthatcher@webrtc.org    socket = ssl_adapter.release();
183f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
184f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
185f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  // Regular logging occurs at the highest level
186f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!logging_label_.empty() && !binary_mode_) {
187f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    socket = new LoggingSocketAdapter(socket, logging_level_,
188f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                                      logging_label_.c_str(), binary_mode_);
189f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
190f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return socket;
191f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
192f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
193f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
194f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
195f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}  // namespace rtc
196