1 /* 2 * libjingle 3 * Copyright 2007, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/autodetectproxy.h" 29 #include "talk/base/httpcommon.h" 30 #include "talk/base/httpcommon-inl.h" 31 #include "talk/base/socketadapters.h" 32 #include "talk/base/ssladapter.h" 33 #include "talk/base/sslsocketfactory.h" 34 35 namespace talk_base { 36 37 /////////////////////////////////////////////////////////////////////////////// 38 // ProxySocketAdapter 39 // TODO: Consider combining AutoDetectProxy and ProxySocketAdapter. I think 40 // the socket adapter is the more appropriate idiom for automatic proxy 41 // detection. We may or may not want to combine proxydetect.* as well. 42 /////////////////////////////////////////////////////////////////////////////// 43 44 class ProxySocketAdapter : public AsyncSocketAdapter { 45 public: 46 ProxySocketAdapter(SslSocketFactory* factory, int type) 47 : AsyncSocketAdapter(NULL), factory_(factory), type_(type), 48 detect_(NULL) { 49 } 50 virtual ~ProxySocketAdapter() { 51 Close(); 52 } 53 54 virtual int Connect(const SocketAddress& addr) { 55 ASSERT(NULL == detect_); 56 ASSERT(NULL == socket_); 57 remote_ = addr; 58 if (remote_.IsAnyIP() && remote_.hostname().empty()) { 59 LOG_F(LS_ERROR) << "Empty address"; 60 return SOCKET_ERROR; 61 } 62 Url<char> url("/", remote_.IPAsString(), remote_.port()); 63 detect_ = new AutoDetectProxy(factory_->agent_); 64 detect_->set_server_url(url.url()); 65 detect_->SignalWorkDone.connect(this, 66 &ProxySocketAdapter::OnProxyDetectionComplete); 67 detect_->Start(); 68 return SOCKET_ERROR; 69 } 70 virtual int GetError() const { 71 if (socket_) { 72 return socket_->GetError(); 73 } 74 return detect_ ? EWOULDBLOCK : EADDRNOTAVAIL; 75 } 76 virtual int Close() { 77 if (socket_) { 78 return socket_->Close(); 79 } 80 if (detect_) { 81 detect_->Destroy(false); 82 detect_ = NULL; 83 } 84 return 0; 85 } 86 virtual ConnState GetState() const { 87 if (socket_) { 88 return socket_->GetState(); 89 } 90 return detect_ ? CS_CONNECTING : CS_CLOSED; 91 } 92 93 private: 94 // AutoDetectProxy Slots 95 void OnProxyDetectionComplete(SignalThread* thread) { 96 ASSERT(detect_ == thread); 97 Attach(factory_->CreateProxySocket(detect_->proxy(), type_)); 98 detect_->Release(); 99 detect_ = NULL; 100 if (0 == AsyncSocketAdapter::Connect(remote_)) { 101 SignalConnectEvent(this); 102 } else if (!IsBlockingError(socket_->GetError())) { 103 SignalCloseEvent(this, socket_->GetError()); 104 } 105 } 106 107 SslSocketFactory* factory_; 108 int type_; 109 SocketAddress remote_; 110 AutoDetectProxy* detect_; 111 }; 112 113 /////////////////////////////////////////////////////////////////////////////// 114 // SslSocketFactory 115 /////////////////////////////////////////////////////////////////////////////// 116 117 Socket* SslSocketFactory::CreateSocket(int type) { 118 return factory_->CreateSocket(type); 119 } 120 121 AsyncSocket* SslSocketFactory::CreateAsyncSocket(int type) { 122 if (autodetect_proxy_) { 123 return new ProxySocketAdapter(this, type); 124 } else { 125 return CreateProxySocket(proxy_, type); 126 } 127 } 128 129 AsyncSocket* SslSocketFactory::CreateProxySocket(const ProxyInfo& proxy, 130 int type) { 131 AsyncSocket* socket = factory_->CreateAsyncSocket(type); 132 if (!socket) 133 return NULL; 134 135 // Binary logging happens at the lowest level 136 if (!logging_label_.empty() && binary_mode_) { 137 socket = new LoggingSocketAdapter(socket, logging_level_, 138 logging_label_.c_str(), binary_mode_); 139 } 140 141 if (proxy.type) { 142 AsyncSocket* proxy_socket = 0; 143 if (proxy_.type == PROXY_SOCKS5) { 144 proxy_socket = new AsyncSocksProxySocket(socket, proxy.address, 145 proxy.username, proxy.password); 146 } else { 147 // Note: we are trying unknown proxies as HTTPS currently 148 AsyncHttpsProxySocket* http_proxy = 149 new AsyncHttpsProxySocket(socket, agent_, proxy.address, 150 proxy.username, proxy.password); 151 http_proxy->SetForceConnect(force_connect_ || !hostname_.empty()); 152 proxy_socket = http_proxy; 153 } 154 if (!proxy_socket) { 155 delete socket; 156 return NULL; 157 } 158 socket = proxy_socket; // for our purposes the proxy is now the socket 159 } 160 161 if (!hostname_.empty()) { 162 if (SSLAdapter* ssl_adapter = SSLAdapter::Create(socket)) { 163 ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_); 164 ssl_adapter->StartSSL(hostname_.c_str(), true); 165 socket = ssl_adapter; 166 } else { 167 LOG_F(LS_ERROR) << "SSL unavailable"; 168 } 169 } 170 171 // Regular logging occurs at the highest level 172 if (!logging_label_.empty() && !binary_mode_) { 173 socket = new LoggingSocketAdapter(socket, logging_level_, 174 logging_label_.c_str(), binary_mode_); 175 } 176 return socket; 177 } 178 179 /////////////////////////////////////////////////////////////////////////////// 180 181 } // namespace talk_base 182