diff options
Diffstat (limited to 'third_party/libjingle/source/talk/base/basicpacketsocketfactory.cc')
-rw-r--r-- | third_party/libjingle/source/talk/base/basicpacketsocketfactory.cc | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/third_party/libjingle/source/talk/base/basicpacketsocketfactory.cc b/third_party/libjingle/source/talk/base/basicpacketsocketfactory.cc new file mode 100644 index 0000000..20173d1 --- /dev/null +++ b/third_party/libjingle/source/talk/base/basicpacketsocketfactory.cc @@ -0,0 +1,159 @@ +/* + * libjingle + * Copyright 2011, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "talk/base/basicpacketsocketfactory.h" + +#include "talk/base/asyncudpsocket.h" +#include "talk/base/asynctcpsocket.h" +#include "talk/base/logging.h" +#include "talk/base/socketadapters.h" +#include "talk/base/thread.h" + +namespace talk_base { + +BasicPacketSocketFactory::BasicPacketSocketFactory( + Thread* thread) + : thread_(thread), + socket_factory_(NULL) { +} + +BasicPacketSocketFactory::BasicPacketSocketFactory( + SocketFactory* socket_factory) + : thread_(NULL), + socket_factory_(socket_factory) { +} + +BasicPacketSocketFactory::~BasicPacketSocketFactory() { +} + +AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket( + const SocketAddress& address, int min_port, int max_port) { + // UDP sockets are simple. + talk_base::AsyncSocket* socket = + socket_factory()->CreateAsyncSocket(SOCK_DGRAM); + if (!socket) { + return NULL; + } + if (BindSocket(socket, address, min_port, max_port) < 0) { + LOG(LS_ERROR) << "UDP bind failed with error " + << socket->GetError(); + delete socket; + return NULL; + } + return new talk_base::AsyncUDPSocket(socket); +} + +AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket( + const SocketAddress& local_address, int min_port, int max_port, + bool listen, bool ssl) { + talk_base::AsyncSocket* socket = + socket_factory()->CreateAsyncSocket(SOCK_STREAM); + if (!socket) { + return NULL; + } + + if (BindSocket(socket, local_address, min_port, max_port) < 0) { + LOG(LS_ERROR) << "TCP bind failed with error " + << socket->GetError(); + delete socket; + return NULL; + } + + // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket. + if (ssl) { + socket = new talk_base::AsyncSSLSocket(socket); + } + + return new talk_base::AsyncTCPSocket(socket, true); +} + +AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket( + const SocketAddress& local_address, const SocketAddress& remote_address, + const ProxyInfo& proxy_info, const std::string& user_agent, bool ssl) { + talk_base::AsyncSocket* socket = + socket_factory()->CreateAsyncSocket(SOCK_STREAM); + if (!socket) { + return NULL; + } + + if (BindSocket(socket, local_address, 0, 0) < 0) { + LOG(LS_ERROR) << "TCP bind failed with error " + << socket->GetError(); + delete socket; + return NULL; + } + + // If using a proxy, wrap the socket in a proxy socket. + if (proxy_info.type == talk_base::PROXY_SOCKS5) { + socket = new talk_base::AsyncSocksProxySocket( + socket, proxy_info.address, proxy_info.username, proxy_info.password); + } else if (proxy_info.type == talk_base::PROXY_HTTPS) { + socket = new talk_base::AsyncHttpsProxySocket( + socket, user_agent, proxy_info.address, + proxy_info.username, proxy_info.password); + } + + // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket. + if (ssl) { + socket = new talk_base::AsyncSSLSocket(socket); + } + + if (socket->Connect(remote_address) < 0) { + LOG(LS_ERROR) << "TCP connect failed with error " + << socket->GetError(); + delete socket; + return NULL; + } + + // Finally, wrap that socket in a TCP packet socket. + return new talk_base::AsyncTCPSocket(socket, false); +} + +int BasicPacketSocketFactory::BindSocket( + AsyncSocket* socket, const SocketAddress& local_address, + int min_port, int max_port) { + int ret = -1; + if (min_port == 0 && max_port == 0) { + // If there's no port range, let the OS pick a port for us. + ret = socket->Bind(local_address); + } else { + // Otherwise, try to find a port in the provided range. + for (int port = min_port; ret < 0 && port <= max_port; ++port) { + ret = socket->Bind(talk_base::SocketAddress(local_address.ip(), port)); + } + } + return ret; +} + +SocketFactory* BasicPacketSocketFactory::socket_factory() { + if (thread_) + return thread_->socketserver(); + else + return socket_factory_; +} + +} // namespace talk_base |