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