1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/*
2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *
4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */
10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/basicpacketsocketfactory.h"
12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
13269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/asyncstuntcpsocket.h"
14269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/base/stun.h"
15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/asynctcpsocket.h"
16269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/asyncudpsocket.h"
17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h"
18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/nethelpers.h"
19269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/physicalsocketserver.h"
20269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/scoped_ptr.h"
21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/socketadapters.h"
22269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/ssladapter.h"
23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/thread.h"
24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace rtc {
26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
27269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgBasicPacketSocketFactory::BasicPacketSocketFactory()
28269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : thread_(Thread::Current()),
29269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      socket_factory_(NULL) {
30269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
31269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgBasicPacketSocketFactory::BasicPacketSocketFactory(Thread* thread)
33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : thread_(thread),
34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      socket_factory_(NULL) {
35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
36269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
37269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgBasicPacketSocketFactory::BasicPacketSocketFactory(
38269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    SocketFactory* socket_factory)
39269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : thread_(NULL),
40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      socket_factory_(socket_factory) {
41269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
42269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
43269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgBasicPacketSocketFactory::~BasicPacketSocketFactory() {
44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgAsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    const SocketAddress& address,
480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint16_t min_port,
490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint16_t max_port) {
50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // UDP sockets are simple.
51269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::AsyncSocket* socket =
52269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      socket_factory()->CreateAsyncSocket(
53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org          address.family(), SOCK_DGRAM);
54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!socket) {
55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
56269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
57269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (BindSocket(socket, address, min_port, max_port) < 0) {
58269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "UDP bind failed with error "
59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                    << socket->GetError();
60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    delete socket;
61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
62269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
63269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return new rtc::AsyncUDPSocket(socket);
64269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
65269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
66269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgAsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
670c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    const SocketAddress& local_address,
680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint16_t min_port,
690c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint16_t max_port,
70332331fb01f8a316ac6d61cf4572478610fb3472pkasting@chromium.org    int opts) {
71269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Fail if TLS is required.
72269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (opts & PacketSocketFactory::OPT_TLS) {
73269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "TLS support currently is not available.";
74269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
75269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
76269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
77269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::AsyncSocket* socket =
78269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      socket_factory()->CreateAsyncSocket(local_address.family(),
79269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                          SOCK_STREAM);
80269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!socket) {
81269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
82269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
83269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
84269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (BindSocket(socket, local_address, min_port, max_port) < 0) {
85269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "TCP bind failed with error "
86269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                  << socket->GetError();
87269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    delete socket;
88269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
89269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
90269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
91269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
92269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (opts & PacketSocketFactory::OPT_SSLTCP) {
93269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
94269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket = new rtc::AsyncSSLSocket(socket);
95269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
96269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
97269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
98269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // See http://go/gtalktcpnodelayexperiment
99269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  socket->SetOption(rtc::Socket::OPT_NODELAY, 1);
100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (opts & PacketSocketFactory::OPT_STUN)
102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return new cricket::AsyncStunTCPSocket(socket, true);
103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return new rtc::AsyncTCPSocket(socket, true);
105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgAsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const SocketAddress& local_address, const SocketAddress& remote_address,
109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const ProxyInfo& proxy_info, const std::string& user_agent, int opts) {
110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::AsyncSocket* socket =
112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!socket) {
114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
117269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (BindSocket(socket, local_address, 0, 0) < 0) {
118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "TCP bind failed with error "
119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                  << socket->GetError();
120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    delete socket;
121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If using a proxy, wrap the socket in a proxy socket.
125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (proxy_info.type == rtc::PROXY_SOCKS5) {
126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket = new rtc::AsyncSocksProxySocket(
127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        socket, proxy_info.address, proxy_info.username, proxy_info.password);
128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else if (proxy_info.type == rtc::PROXY_HTTPS) {
129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket = new rtc::AsyncHttpsProxySocket(
130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        socket, user_agent, proxy_info.address,
131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        proxy_info.username, proxy_info.password);
132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If using TLS, wrap the socket in an SSL adapter.
135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (opts & PacketSocketFactory::OPT_TLS) {
136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(!(opts & PacketSocketFactory::OPT_SSLTCP));
137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::SSLAdapter* ssl_adapter = rtc::SSLAdapter::Create(socket);
139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (!ssl_adapter) {
140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return NULL;
141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket = ssl_adapter;
144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (ssl_adapter->StartSSL(remote_address.hostname().c_str(), false) != 0) {
146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      delete ssl_adapter;
147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      return NULL;
148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else if (opts & PacketSocketFactory::OPT_SSLTCP) {
152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    socket = new rtc::AsyncSSLSocket(socket);
154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (socket->Connect(remote_address) < 0) {
157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "TCP connect failed with error "
158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                  << socket->GetError();
159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    delete socket;
160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return NULL;
161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Finally, wrap that socket in a TCP or STUN TCP packet socket.
164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  AsyncPacketSocket* tcp_socket;
165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (opts & PacketSocketFactory::OPT_STUN) {
166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    tcp_socket = new rtc::AsyncTCPSocket(socket, false);
169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // See http://go/gtalktcpnodelayexperiment
173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  tcp_socket->SetOption(rtc::Socket::OPT_NODELAY, 1);
174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return tcp_socket;
176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgAsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return new rtc::AsyncResolver();
180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
1820c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmint BasicPacketSocketFactory::BindSocket(AsyncSocket* socket,
1830c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                         const SocketAddress& local_address,
1840c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                         uint16_t min_port,
1850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                         uint16_t max_port) {
186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  int ret = -1;
187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (min_port == 0 && max_port == 0) {
188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // If there's no port range, let the OS pick a port for us.
189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ret = socket->Bind(local_address);
190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
191269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    // Otherwise, try to find a port in the provided range.
192269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    for (int port = min_port; ret < 0 && port <= max_port; ++port) {
193269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      ret = socket->Bind(rtc::SocketAddress(local_address.ipaddr(),
194269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                  port));
195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return ret;
198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
199269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
200269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgSocketFactory* BasicPacketSocketFactory::socket_factory() {
201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (thread_) {
202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(thread_ == Thread::Current());
203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return thread_->socketserver();
204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  } else {
205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return socket_factory_;
206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
208269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
209269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}  // namespace rtc
210