1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/* 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * libjingle 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Copyright 2011, Google Inc. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Redistribution and use in source and binary forms, with or without 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * modification, are permitted provided that the following conditions are met: 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 1. Redistributions of source code must retain the above copyright notice, 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * this list of conditions and the following disclaimer. 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 2. Redistributions in binary form must reproduce the above copyright notice, 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * this list of conditions and the following disclaimer in the documentation 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * and/or other materials provided with the distribution. 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 3. The name of the author may not be used to endorse or promote products 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * derived from this software without specific prior written permission. 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "talk/base/basicpacketsocketfactory.h" 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "talk/base/asyncudpsocket.h" 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "talk/base/asynctcpsocket.h" 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "talk/base/logging.h" 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "talk/base/socketadapters.h" 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "talk/base/thread.h" 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace talk_base { 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBasicPacketSocketFactory::BasicPacketSocketFactory( 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Thread* thread) 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : thread_(thread), 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_factory_(NULL) { 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBasicPacketSocketFactory::BasicPacketSocketFactory( 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SocketFactory* socket_factory) 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : thread_(NULL), 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_factory_(socket_factory) { 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBasicPacketSocketFactory::~BasicPacketSocketFactory() { 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket( 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SocketAddress& address, int min_port, int max_port) { 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // UDP sockets are simple. 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen talk_base::AsyncSocket* socket = 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_factory()->CreateAsyncSocket(SOCK_DGRAM); 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!socket) { 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (BindSocket(socket, address, min_port, max_port) < 0) { 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(LS_ERROR) << "UDP bind failed with error " 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << socket->GetError(); 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete socket; 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return new talk_base::AsyncUDPSocket(socket); 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket( 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SocketAddress& local_address, int min_port, int max_port, 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool listen, bool ssl) { 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen talk_base::AsyncSocket* socket = 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_factory()->CreateAsyncSocket(SOCK_STREAM); 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!socket) { 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (BindSocket(socket, local_address, min_port, max_port) < 0) { 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(LS_ERROR) << "TCP bind failed with error " 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << socket->GetError(); 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete socket; 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket. 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (ssl) { 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket = new talk_base::AsyncSSLSocket(socket); 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return new talk_base::AsyncTCPSocket(socket, true); 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenAsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket( 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SocketAddress& local_address, const SocketAddress& remote_address, 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ProxyInfo& proxy_info, const std::string& user_agent, bool ssl) { 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen talk_base::AsyncSocket* socket = 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket_factory()->CreateAsyncSocket(SOCK_STREAM); 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!socket) { 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (BindSocket(socket, local_address, 0, 0) < 0) { 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(LS_ERROR) << "TCP bind failed with error " 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << socket->GetError(); 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete socket; 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If using a proxy, wrap the socket in a proxy socket. 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (proxy_info.type == talk_base::PROXY_SOCKS5) { 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket = new talk_base::AsyncSocksProxySocket( 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket, proxy_info.address, proxy_info.username, proxy_info.password); 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (proxy_info.type == talk_base::PROXY_HTTPS) { 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket = new talk_base::AsyncHttpsProxySocket( 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket, user_agent, proxy_info.address, 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen proxy_info.username, proxy_info.password); 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket. 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (ssl) { 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen socket = new talk_base::AsyncSSLSocket(socket); 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (socket->Connect(remote_address) < 0) { 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(LS_ERROR) << "TCP connect failed with error " 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << socket->GetError(); 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete socket; 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Finally, wrap that socket in a TCP packet socket. 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return new talk_base::AsyncTCPSocket(socket, false); 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint BasicPacketSocketFactory::BindSocket( 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AsyncSocket* socket, const SocketAddress& local_address, 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int min_port, int max_port) { 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int ret = -1; 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (min_port == 0 && max_port == 0) { 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If there's no port range, let the OS pick a port for us. 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ret = socket->Bind(local_address); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Otherwise, try to find a port in the provided range. 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int port = min_port; ret < 0 && port <= max_port; ++port) { 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ret = socket->Bind(talk_base::SocketAddress(local_address.ip(), port)); 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ret; 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSocketFactory* BasicPacketSocketFactory::socket_factory() { 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (thread_) 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return thread_->socketserver(); 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return socket_factory_; 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace talk_base 160