1 /* 2 * libjingle 3 * Copyright 2011, 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/basicpacketsocketfactory.h" 29 30 #include "talk/base/asyncudpsocket.h" 31 #include "talk/base/asynctcpsocket.h" 32 #include "talk/base/logging.h" 33 #include "talk/base/socketadapters.h" 34 #include "talk/base/thread.h" 35 36 namespace talk_base { 37 38 BasicPacketSocketFactory::BasicPacketSocketFactory( 39 Thread* thread) 40 : thread_(thread), 41 socket_factory_(NULL) { 42 } 43 44 BasicPacketSocketFactory::BasicPacketSocketFactory( 45 SocketFactory* socket_factory) 46 : thread_(NULL), 47 socket_factory_(socket_factory) { 48 } 49 50 BasicPacketSocketFactory::~BasicPacketSocketFactory() { 51 } 52 53 AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket( 54 const SocketAddress& address, int min_port, int max_port) { 55 // UDP sockets are simple. 56 talk_base::AsyncSocket* socket = 57 socket_factory()->CreateAsyncSocket(SOCK_DGRAM); 58 if (!socket) { 59 return NULL; 60 } 61 if (BindSocket(socket, address, min_port, max_port) < 0) { 62 LOG(LS_ERROR) << "UDP bind failed with error " 63 << socket->GetError(); 64 delete socket; 65 return NULL; 66 } 67 return new talk_base::AsyncUDPSocket(socket); 68 } 69 70 AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket( 71 const SocketAddress& local_address, int min_port, int max_port, 72 bool listen, bool ssl) { 73 talk_base::AsyncSocket* socket = 74 socket_factory()->CreateAsyncSocket(SOCK_STREAM); 75 if (!socket) { 76 return NULL; 77 } 78 79 if (BindSocket(socket, local_address, min_port, max_port) < 0) { 80 LOG(LS_ERROR) << "TCP bind failed with error " 81 << socket->GetError(); 82 delete socket; 83 return NULL; 84 } 85 86 // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket. 87 if (ssl) { 88 socket = new talk_base::AsyncSSLSocket(socket); 89 } 90 91 return new talk_base::AsyncTCPSocket(socket, true); 92 } 93 94 AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket( 95 const SocketAddress& local_address, const SocketAddress& remote_address, 96 const ProxyInfo& proxy_info, const std::string& user_agent, bool ssl) { 97 talk_base::AsyncSocket* socket = 98 socket_factory()->CreateAsyncSocket(SOCK_STREAM); 99 if (!socket) { 100 return NULL; 101 } 102 103 if (BindSocket(socket, local_address, 0, 0) < 0) { 104 LOG(LS_ERROR) << "TCP bind failed with error " 105 << socket->GetError(); 106 delete socket; 107 return NULL; 108 } 109 110 // If using a proxy, wrap the socket in a proxy socket. 111 if (proxy_info.type == talk_base::PROXY_SOCKS5) { 112 socket = new talk_base::AsyncSocksProxySocket( 113 socket, proxy_info.address, proxy_info.username, proxy_info.password); 114 } else if (proxy_info.type == talk_base::PROXY_HTTPS) { 115 socket = new talk_base::AsyncHttpsProxySocket( 116 socket, user_agent, proxy_info.address, 117 proxy_info.username, proxy_info.password); 118 } 119 120 // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket. 121 if (ssl) { 122 socket = new talk_base::AsyncSSLSocket(socket); 123 } 124 125 if (socket->Connect(remote_address) < 0) { 126 LOG(LS_ERROR) << "TCP connect failed with error " 127 << socket->GetError(); 128 delete socket; 129 return NULL; 130 } 131 132 // Finally, wrap that socket in a TCP packet socket. 133 return new talk_base::AsyncTCPSocket(socket, false); 134 } 135 136 int BasicPacketSocketFactory::BindSocket( 137 AsyncSocket* socket, const SocketAddress& local_address, 138 int min_port, int max_port) { 139 int ret = -1; 140 if (min_port == 0 && max_port == 0) { 141 // If there's no port range, let the OS pick a port for us. 142 ret = socket->Bind(local_address); 143 } else { 144 // Otherwise, try to find a port in the provided range. 145 for (int port = min_port; ret < 0 && port <= max_port; ++port) { 146 ret = socket->Bind(talk_base::SocketAddress(local_address.ip(), port)); 147 } 148 } 149 return ret; 150 } 151 152 SocketFactory* BasicPacketSocketFactory::socket_factory() { 153 if (thread_) 154 return thread_->socketserver(); 155 else 156 return socket_factory_; 157 } 158 159 } // namespace talk_base 160