blob: b794904411fab6cb3ef6a7a01e2e004b785d2480 [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
hnsl04833622017-01-09 08:35:45 -080090 // If using fake TLS, wrap the TCP socket in a pseudo-SSL socket.
91 if (opts & PacketSocketFactory::OPT_TLS_FAKE) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000092 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
hnsl04833622017-01-09 08:35:45 -0800132 // Assert that at most one TLS option is used.
133 int tlsOpts =
134 opts & (PacketSocketFactory::OPT_TLS | PacketSocketFactory::OPT_TLS_FAKE |
135 PacketSocketFactory::OPT_TLS_INSECURE);
136 ASSERT((tlsOpts & (tlsOpts - 1)) == 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000137
hnsl04833622017-01-09 08:35:45 -0800138 if ((tlsOpts & PacketSocketFactory::OPT_TLS) ||
139 (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE)) {
140 // Using TLS, wrap the socket in an SSL adapter.
johan57e13de2016-10-25 10:15:06 -0700141 SSLAdapter* ssl_adapter = SSLAdapter::Create(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000142 if (!ssl_adapter) {
143 return NULL;
144 }
145
hnsl04833622017-01-09 08:35:45 -0800146 if (tlsOpts & PacketSocketFactory::OPT_TLS_INSECURE) {
147 ssl_adapter->set_ignore_bad_cert(true);
148 }
149
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000150 socket = ssl_adapter;
151
152 if (ssl_adapter->StartSSL(remote_address.hostname().c_str(), false) != 0) {
153 delete ssl_adapter;
154 return NULL;
155 }
156
hnsl04833622017-01-09 08:35:45 -0800157 } else if (tlsOpts & PacketSocketFactory::OPT_TLS_FAKE) {
158 // Using fake TLS, wrap the TCP socket in a pseudo-SSL socket.
johan57e13de2016-10-25 10:15:06 -0700159 socket = new AsyncSSLSocket(socket);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000160 }
161
162 if (socket->Connect(remote_address) < 0) {
163 LOG(LS_ERROR) << "TCP connect failed with error "
164 << socket->GetError();
165 delete socket;
166 return NULL;
167 }
168
169 // Finally, wrap that socket in a TCP or STUN TCP packet socket.
170 AsyncPacketSocket* tcp_socket;
171 if (opts & PacketSocketFactory::OPT_STUN) {
172 tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
173 } else {
johan57e13de2016-10-25 10:15:06 -0700174 tcp_socket = new AsyncTCPSocket(socket, false);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000175 }
176
177 // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
178 // See http://go/gtalktcpnodelayexperiment
johan57e13de2016-10-25 10:15:06 -0700179 tcp_socket->SetOption(Socket::OPT_NODELAY, 1);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000180
181 return tcp_socket;
182}
183
184AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
johan57e13de2016-10-25 10:15:06 -0700185 return new AsyncResolver();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000186}
187
Peter Boström0c4e06b2015-10-07 12:23:21 +0200188int BasicPacketSocketFactory::BindSocket(AsyncSocket* socket,
189 const SocketAddress& local_address,
190 uint16_t min_port,
191 uint16_t max_port) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000192 int ret = -1;
193 if (min_port == 0 && max_port == 0) {
194 // If there's no port range, let the OS pick a port for us.
195 ret = socket->Bind(local_address);
196 } else {
197 // Otherwise, try to find a port in the provided range.
198 for (int port = min_port; ret < 0 && port <= max_port; ++port) {
johan57e13de2016-10-25 10:15:06 -0700199 ret = socket->Bind(SocketAddress(local_address.ipaddr(), port));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000200 }
201 }
202 return ret;
203}
204
205SocketFactory* BasicPacketSocketFactory::socket_factory() {
206 if (thread_) {
207 ASSERT(thread_ == Thread::Current());
208 return thread_->socketserver();
209 } else {
210 return socket_factory_;
211 }
212}
213
214} // namespace rtc