blob: 51e9b07fc0c660c0b7e743ea0b8ab75ba5d514a5 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2011 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/p2p/base/basicpacketsocketfactory.h"
12
johan57e13de2016-10-25 10:15:06 -070013#include <string>
14
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000015#include "webrtc/p2p/base/asyncstuntcpsocket.h"
16#include "webrtc/p2p/base/stun.h"
17#include "webrtc/base/asynctcpsocket.h"
18#include "webrtc/base/asyncudpsocket.h"
19#include "webrtc/base/logging.h"
20#include "webrtc/base/nethelpers.h"
21#include "webrtc/base/physicalsocketserver.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000022#include "webrtc/base/socketadapters.h"
23#include "webrtc/base/ssladapter.h"
24#include "webrtc/base/thread.h"
25
26namespace rtc {
27
28BasicPacketSocketFactory::BasicPacketSocketFactory()
29 : thread_(Thread::Current()),
30 socket_factory_(NULL) {
31}
32
33BasicPacketSocketFactory::BasicPacketSocketFactory(Thread* thread)
34 : thread_(thread),
35 socket_factory_(NULL) {
36}
37
38BasicPacketSocketFactory::BasicPacketSocketFactory(
39 SocketFactory* socket_factory)
40 : thread_(NULL),
41 socket_factory_(socket_factory) {
42}
43
44BasicPacketSocketFactory::~BasicPacketSocketFactory() {
45}
46
47AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
Peter Boström0c4e06b2015-10-07 12:23:21 +020048 const SocketAddress& address,
49 uint16_t min_port,
50 uint16_t max_port) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000051 // UDP sockets are simple.
johan57e13de2016-10-25 10:15:06 -070052 AsyncSocket* socket =
53 socket_factory()->CreateAsyncSocket(address.family(), SOCK_DGRAM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000054 if (!socket) {
55 return NULL;
56 }
57 if (BindSocket(socket, address, min_port, max_port) < 0) {
58 LOG(LS_ERROR) << "UDP bind failed with error "
59 << socket->GetError();
60 delete socket;
61 return NULL;
62 }
johan57e13de2016-10-25 10:15:06 -070063 return new AsyncUDPSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000064}
65
66AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
Peter Boström0c4e06b2015-10-07 12:23:21 +020067 const SocketAddress& local_address,
68 uint16_t min_port,
69 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +000070 int opts) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000071 // Fail if TLS is required.
72 if (opts & PacketSocketFactory::OPT_TLS) {
73 LOG(LS_ERROR) << "TLS support currently is not available.";
74 return NULL;
75 }
76
johan57e13de2016-10-25 10:15:06 -070077 AsyncSocket* socket =
78 socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000079 if (!socket) {
80 return NULL;
81 }
82
83 if (BindSocket(socket, local_address, min_port, max_port) < 0) {
84 LOG(LS_ERROR) << "TCP bind failed with error "
85 << socket->GetError();
86 delete socket;
87 return NULL;
88 }
89
90 // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
91 if (opts & PacketSocketFactory::OPT_SSLTCP) {
92 ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
johan57e13de2016-10-25 10:15:06 -070093 socket = new AsyncSSLSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000094 }
95
96 // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
97 // See http://go/gtalktcpnodelayexperiment
johan57e13de2016-10-25 10:15:06 -070098 socket->SetOption(Socket::OPT_NODELAY, 1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000099
100 if (opts & PacketSocketFactory::OPT_STUN)
101 return new cricket::AsyncStunTCPSocket(socket, true);
102
johan57e13de2016-10-25 10:15:06 -0700103 return new AsyncTCPSocket(socket, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000104}
105
106AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
107 const SocketAddress& local_address, const SocketAddress& remote_address,
108 const ProxyInfo& proxy_info, const std::string& user_agent, int opts) {
johan57e13de2016-10-25 10:15:06 -0700109 AsyncSocket* socket =
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000110 socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
111 if (!socket) {
112 return NULL;
113 }
114
115 if (BindSocket(socket, local_address, 0, 0) < 0) {
116 LOG(LS_ERROR) << "TCP bind failed with error "
117 << socket->GetError();
118 delete socket;
119 return NULL;
120 }
121
122 // If using a proxy, wrap the socket in a proxy socket.
johan57e13de2016-10-25 10:15:06 -0700123 if (proxy_info.type == PROXY_SOCKS5) {
124 socket = new AsyncSocksProxySocket(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000125 socket, proxy_info.address, proxy_info.username, proxy_info.password);
johan57e13de2016-10-25 10:15:06 -0700126 } else if (proxy_info.type == PROXY_HTTPS) {
127 socket =
128 new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
129 proxy_info.username, proxy_info.password);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000130 }
131
132 // If using TLS, wrap the socket in an SSL adapter.
133 if (opts & PacketSocketFactory::OPT_TLS) {
134 ASSERT(!(opts & PacketSocketFactory::OPT_SSLTCP));
135
johan57e13de2016-10-25 10:15:06 -0700136 SSLAdapter* ssl_adapter = SSLAdapter::Create(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000137 if (!ssl_adapter) {
138 return NULL;
139 }
140
141 socket = ssl_adapter;
142
143 if (ssl_adapter->StartSSL(remote_address.hostname().c_str(), false) != 0) {
144 delete ssl_adapter;
145 return NULL;
146 }
147
148 // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
149 } else if (opts & PacketSocketFactory::OPT_SSLTCP) {
150 ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
johan57e13de2016-10-25 10:15:06 -0700151 socket = new AsyncSSLSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000152 }
153
154 if (socket->Connect(remote_address) < 0) {
155 LOG(LS_ERROR) << "TCP connect failed with error "
156 << socket->GetError();
157 delete socket;
158 return NULL;
159 }
160
161 // Finally, wrap that socket in a TCP or STUN TCP packet socket.
162 AsyncPacketSocket* tcp_socket;
163 if (opts & PacketSocketFactory::OPT_STUN) {
164 tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
165 } else {
johan57e13de2016-10-25 10:15:06 -0700166 tcp_socket = new AsyncTCPSocket(socket, false);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000167 }
168
169 // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
170 // See http://go/gtalktcpnodelayexperiment
johan57e13de2016-10-25 10:15:06 -0700171 tcp_socket->SetOption(Socket::OPT_NODELAY, 1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000172
173 return tcp_socket;
174}
175
176AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
johan57e13de2016-10-25 10:15:06 -0700177 return new AsyncResolver();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000178}
179
Peter Boström0c4e06b2015-10-07 12:23:21 +0200180int BasicPacketSocketFactory::BindSocket(AsyncSocket* socket,
181 const SocketAddress& local_address,
182 uint16_t min_port,
183 uint16_t max_port) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000184 int ret = -1;
185 if (min_port == 0 && max_port == 0) {
186 // If there's no port range, let the OS pick a port for us.
187 ret = socket->Bind(local_address);
188 } else {
189 // Otherwise, try to find a port in the provided range.
190 for (int port = min_port; ret < 0 && port <= max_port; ++port) {
johan57e13de2016-10-25 10:15:06 -0700191 ret = socket->Bind(SocketAddress(local_address.ipaddr(), port));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000192 }
193 }
194 return ret;
195}
196
197SocketFactory* BasicPacketSocketFactory::socket_factory() {
198 if (thread_) {
199 ASSERT(thread_ == Thread::Current());
200 return thread_->socketserver();
201 } else {
202 return socket_factory_;
203 }
204}
205
206} // namespace rtc