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 family, int type) 47 : AsyncSocketAdapter(NULL), factory_(factory), family_(family), 48 type_(type), 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_.HostAsURIString(), 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(), family_, 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 family_; 109 int type_; 110 SocketAddress remote_; 111 AutoDetectProxy* detect_; 112 }; 113 114 /////////////////////////////////////////////////////////////////////////////// 115 // SslSocketFactory 116 /////////////////////////////////////////////////////////////////////////////// 117 118 Socket* SslSocketFactory::CreateSocket(int type) { 119 return CreateSocket(AF_INET, type); 120 } 121 122 Socket* SslSocketFactory::CreateSocket(int family, int type) { 123 return factory_->CreateSocket(family, type); 124 } 125 126 AsyncSocket* SslSocketFactory::CreateAsyncSocket(int type) { 127 return CreateAsyncSocket(AF_INET, type); 128 } 129 130 AsyncSocket* SslSocketFactory::CreateAsyncSocket(int family, int type) { 131 if (autodetect_proxy_) { 132 return new ProxySocketAdapter(this, family, type); 133 } else { 134 return CreateProxySocket(proxy_, family, type); 135 } 136 } 137 138 139 AsyncSocket* SslSocketFactory::CreateProxySocket(const ProxyInfo& proxy, 140 int family, 141 int type) { 142 AsyncSocket* socket = factory_->CreateAsyncSocket(family, type); 143 if (!socket) 144 return NULL; 145 146 // Binary logging happens at the lowest level 147 if (!logging_label_.empty() && binary_mode_) { 148 socket = new LoggingSocketAdapter(socket, logging_level_, 149 logging_label_.c_str(), binary_mode_); 150 } 151 152 if (proxy.type) { 153 AsyncSocket* proxy_socket = 0; 154 if (proxy_.type == PROXY_SOCKS5) { 155 proxy_socket = new AsyncSocksProxySocket(socket, proxy.address, 156 proxy.username, proxy.password); 157 } else { 158 // Note: we are trying unknown proxies as HTTPS currently 159 AsyncHttpsProxySocket* http_proxy = 160 new AsyncHttpsProxySocket(socket, agent_, proxy.address, 161 proxy.username, proxy.password); 162 http_proxy->SetForceConnect(force_connect_ || !hostname_.empty()); 163 proxy_socket = http_proxy; 164 } 165 if (!proxy_socket) { 166 delete socket; 167 return NULL; 168 } 169 socket = proxy_socket; // for our purposes the proxy is now the socket 170 } 171 172 if (!hostname_.empty()) { 173 if (SSLAdapter* ssl_adapter = SSLAdapter::Create(socket)) { 174 ssl_adapter->set_ignore_bad_cert(ignore_bad_cert_); 175 ssl_adapter->StartSSL(hostname_.c_str(), true); 176 socket = ssl_adapter; 177 } else { 178 LOG_F(LS_ERROR) << "SSL unavailable"; 179 } 180 } 181 182 // Regular logging occurs at the highest level 183 if (!logging_label_.empty() && !binary_mode_) { 184 socket = new LoggingSocketAdapter(socket, logging_level_, 185 logging_label_.c_str(), binary_mode_); 186 } 187 return socket; 188 } 189 190 /////////////////////////////////////////////////////////////////////////////// 191 192 } // namespace talk_base 193